Dav*_*son 35 c# list data-partitioning
我想通过指定每个分区中的元素数量将列表分区为列表列表.
例如,假设我有列表{1,2,... 11},并且想要对其进行分区,使得每个集合具有4个元素,最后一个集合尽可能多地填充元素.生成的分区看起来像{{1..4},{5..8},{9..11}}
写这个的优雅方式是什么?
And*_*are 52
这是一个扩展方法,可以执行您想要的操作:
public static IEnumerable<List<T>> Partition<T>(this IList<T> source, Int32 size)
{
for (int i = 0; i < (source.Count / size) + (source.Count % size > 0 ? 1 : 0); i++)
yield return new List<T>(source.Skip(size * i).Take(size));
}
Run Code Online (Sandbox Code Playgroud)
编辑:这是一个更清洁的功能版本:
public static IEnumerable<List<T>> Partition<T>(this IList<T> source, Int32 size)
{
for (int i = 0; i < Math.Ceiling(source.Count / (Double)size); i++)
yield return new List<T>(source.Skip(size * i).Take(size));
}
Run Code Online (Sandbox Code Playgroud)
Sco*_*vey 30
使用LINQ,您可以在一行代码中剪切您的组,就像这样......
var x = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
var groups = x.Select((i, index) => new
{
i,
index
}).GroupBy(group => group.index / 4, element => element.i);
Run Code Online (Sandbox Code Playgroud)
然后你可以迭代这些组,如下所示......
foreach (var group in groups)
{
Console.WriteLine("Group: {0}", group.Key);
foreach (var item in group)
{
Console.WriteLine("\tValue: {0}", item);
}
}
Run Code Online (Sandbox Code Playgroud)
你会得到一个看起来像这样的输出......
Group: 0
Value: 1
Value: 2
Value: 3
Value: 4
Group: 1
Value: 5
Value: 6
Value: 7
Value: 8
Group: 2
Value: 9
Value: 10
Value: 11
Run Code Online (Sandbox Code Playgroud)
Joe*_*Joe 11
像(未经测试的航空代码):
IEnumerable<IList<T>> PartitionList<T>(IList<T> list, int maxCount)
{
List<T> partialList = new List<T>(maxCount);
foreach(T item in list)
{
if (partialList.Count == maxCount)
{
yield return partialList;
partialList = new List<T>(maxCount);
}
partialList.Add(item);
}
if (partialList.Count > 0) yield return partialList;
}
Run Code Online (Sandbox Code Playgroud)
这将返回列表的枚举而不是列表列表,但您可以轻松地将结果包装在列表中:
IList<IList<T>> listOfLists = new List<T>(PartitionList<T>(list, maxCount));
Run Code Online (Sandbox Code Playgroud)
避免分组,数学和重复.
该方法避免了不必要的计算,比较和分配.包括参数验证.
public static IEnumerable<IList<T>> Partition<T>(
this IEnumerable<T> source,
int size)
{
if (size < 2)
{
throw new ArgumentOutOfRangeException(
nameof(size),
size,
"Must be greater or equal to 2.");
}
T[] partition;
int count;
using (var e = source.GetEnumerator())
{
if (e.MoveNext())
{
partition = new T[size];
partition[0] = e.Current;
count = 1;
}
else
{
yield break;
}
while(e.MoveNext())
{
partition[count] = e.Current;
count++;
if (count == size)
{
yield return partition;
count = 0;
partition = new T[size];
}
}
}
if (count > 0)
{
Array.Resize(ref partition, count);
yield return partition;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
25565 次 |
最近记录: |