我有一个项目列表(不确定它们是偶数还是奇数)。我想做的是,从5对记录(实际上是一个列表)中拾取记录,创建另一个列表,然后将这5对列表插入到新列表中。
谢谢
我可以这样做来创建一组物品
MyList
.Zip(Enumerable.Range(0, MyList.Count()),
(s, r) => new {
Group = r / 5,
Item = s })
.GroupBy(i => i.Group,
g => g.Item)
.ToList();
但是我想生成一个嵌套列表。
答案 0 :(得分:0)
不确定我是否正确理解了您的目标,但是您可以尝试使用Dictionary:
MyList.Zip(Enumerable.Range(0, MyList.Count()),
(s, r) => new { Group = r / 5, Item = s })
.GroupBy(i => i.Group, g => g.Item)
.ToDictionary(g => g.Key, g => g.ToList());
答案 1 :(得分:0)
如果您有一系列物品
var items = Enumerable.Range(1, 20);
您想一次服用5张
var setSize = 5;
您可以按索引遍历集合,一次将5个作为列表,然后将所有5个列表放入一个外部列表中
Enumerable.Range(0, items.Count() - setSize).Select(x => items.Skip(x).Take(setSize).ToList()).ToList()
结果(来自C#交互式shell)看起来像
List<List<int>>(15) {
List<int>(5) { 1, 2, 3, 4, 5 },
List<int>(5) { 2, 3, 4, 5, 6 },
List<int>(5) { 3, 4, 5, 6, 7 },
List<int>(5) { 4, 5, 6, 7, 8 },
List<int>(5) { 5, 6, 7, 8, 9 },
List<int>(5) { 6, 7, 8, 9, 10 },
List<int>(5) { 7, 8, 9, 10, 11 },
List<int>(5) { 8, 9, 10, 11, 12 },
List<int>(5) { 9, 10, 11, 12, 13 },
List<int>(5) { 10, 11, 12, 13, 14 },
List<int>(5) { 11, 12, 13, 14, 15 },
List<int>(5) { 12, 13, 14, 15, 16 },
List<int>(5) { 13, 14, 15, 16, 17 },
List<int>(5) { 14, 15, 16, 17, 18 },
List<int>(5) { 15, 16, 17, 18, 19 }
}
如果您希望每个项目在每个列表中仅显示一次,则可以更改以上内容。假设元素数量奇数:
var items = Enumerable.Range(1, 11);
您想要更改用于索引到集合中的初始范围。与其在每个索引上一次取5,不如在每次迭代中将索引向上跳5。唯一棘手的部分是确保在集合除以您要采用的元素数量时进行处理。您不希望最后出现一个空列表。也就是说,这是不正确的:
Enumerable.Range(0, items.Count() / setSize).Select( // don't do this
然后是
Enumerable.Range(0, ((items.Count() - 1) / setSize) + 1).Select(x => items.Skip(setSize * x).Take(setSize).ToList()).ToList();
结果(来自C#交互式shell)看起来像
List<List<int>>(3) {
List<int>(5) { 1, 2, 3, 4, 5 },
List<int>(5) { 6, 7, 8, 9, 10 },
List<int>(1) { 11 }
}
答案 2 :(得分:0)
您似乎想以每批5个项目的形式批量 个元素。 MoreLinq软件包已经为此提供了Batch运算符:
var items=Enumerable.Range(0,17);
var batches=items.Batch(5);
foreach(var batch in batches)
{
Console.WriteLine(String.Join(" - ",batch));
}
这产生了:
0 - 1 - 2 - 3 - 4
5 - 6 - 7 - 8 - 9
10 - 11 - 12 - 13 - 14
15 - 16
这比分组要快得多,因为它只对集合进行一次迭代。
MoreLINQ还具有其他运算符,例如Window,WindowLeft和WindowRight,它们可生成值的滑动窗口。 items.Window(5)
会产生:
0 - 1 - 2 - 3 - 4
1 - 2 - 3 - 4 - 5
...
11 - 12 - 13 - 14 - 15
12 - 13 - 14 - 15 - 16
实施
操作员的实现非常简单,您只需将其复制到项目中即可
public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(this IEnumerable<TSource> source, int size)
{
return Batch(source, size, x => x);
}
public static IEnumerable<TResult> Batch<TSource, TResult>( IEnumerable<TSource> source, int size,
Func<IEnumerable<TSource>, TResult> resultSelector)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size));
if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector));
return _(); IEnumerable<TResult> _()
{
TSource[] bucket = null;
var count = 0;
foreach (var item in source)
{
if (bucket == null)
{
bucket = new TSource[size];
}
bucket[count++] = item;
// The bucket is fully buffered before it's yielded
if (count != size)
{
continue;
}
yield return resultSelector(bucket);
bucket = null;
count = 0;
}
// Return the last bucket with all remaining elements
if (bucket != null && count > 0)
{
Array.Resize(ref bucket, count);
yield return resultSelector(bucket);
}
}
}
代码使用数组来提高效率。如果您确实想使用可变列表,则可以将bucket
的类型更改为List<T>
,例如:
if (bucket == null)
{
bucket = new List<TSource>(size); //IMPORTANT: set the capacity to avoid reallocations
}
bucket.Add(item);
...
答案 3 :(得分:0)
为什么不只是GroupBy
?
using System.Linq;
...
int groupSize = 5;
var result = MyList
.Select((item, index) => new {
item,
index
})
.GroupBy(pair => pair.index / groupSize,
pair => pair.item)
.Select(group => group.ToList())
.ToList();