我有一个包含n Foo项目的List。 Foo包含一个长属性Foo.FileSize。 现在我想将此列表拆分为具有n个元素的子列表,这些元素是FileSize的总和 不超过10000.Cource中有Foo.FileSize的项目也超过10000。对于这种特殊情况,只需要一个只有这个项目的子列表。
请有人建议吗?
const long maxdownloadsize = 10485760;
long actualdownloadsize = 0;
List<TI> downloadTI = new List<TI>();
for (int i = 0; i < comparedTI.Count; i++)
{
var ti = comparedTI[i];
actualdownloadsize += ti.FileSize;
downloadTI.Add(ti);
if (actualdownloadsize > maxdownloadsize || i == comparedTI.Count-1)
{
actualdownloadsize = 0;
AddToList(downloadTI);
downloadTI = new List<TI>();
}
}
答案 0 :(得分:0)
老实说,以传统方式而不是Linq更容易做到这一点,因为序列中每个元素所需的转换方法需要知道所有先前的元素。所以,你可以这样做:
public static IEnumerable<List<T>> Partition<T>(IEnumerable<T> list, Func<T, long> getValue, long maxSum)
{
long sum = 0;
int partition = 0;
var query = list.Select((i, index) =>
{
if (index == 0)
{
// Reset the external partition counter in case the query is run multiple times.
sum = 0;
partition = 0;
}
var value = getValue(i);
sum = sum + value;
if (sum > maxSum)
{
sum = value;
partition++;
}
return new KeyValuePair<int, T>(partition, i);
})
.GroupBy(pair => pair.Key)
.Select(g => g.Select(pair => pair.Value).ToList());
return query;
}
然后称之为:
var list = new List<Foo>();
// Fill up the list.
var query = Partition(list, f => f.FileSize, 10000);
var partition = query.ToList();
虽然这符合“使用LINQ将List<T>
拆分为Sublists<T>
”的要求,但实际上效率低于直接执行。
答案 1 :(得分:0)
这不是很好,但您可以使用局部变量和LINQ GroupBy()将列表按大小拆分。此外,此功能没有优化,因此您可能无法获得最佳组数。换句话说,如果列表中间有一个大文件,那么它将启动一个新组,即使可以将更多更小的文件放入当前组中。
var maxGroupSize = 10485760;
var groupId = 0;
var groupCount = 0;
long groupSize = 0;
var groups = files.GroupBy(f =>
{
var size = f.FileSize;
if ((groupCount > 0) && ((groupSize + size) > maxGroupSize))
{
// Start a new group and reset count and sum
groupId++;
groupCount = 0;
groupSize = 0;
}
groupSize += size;
groupCount++;
return groupId;
});
GroupBy
方法返回IGrouping<TKey, TSource>
,如果需要将其转换为List,请执行以下操作(假设示例代码中的TSource
类型为TI
) :
List<TI> downloadTI = groups.Select(p => new List<TI>(groups[p.Key]));