使用LINQ根据条件将列表拆分为多个列表

时间:2015-11-03 06:01:31

标签: c# linq

我有一个整数列表,我希望根据满足某个标准将其拆分为2个或更多列表。例如:

List<int> myList = new List<int>();
myList.Add(100);
myList.Add(200);
myList.Add(300);
myList.Add(400);
myList.Add(200);
myList.Add(500);

我想将列表拆分成几个列表,每个列表包含总计&lt; = 600的所有项目。在上面,它将产生3个单独的List对象。

  • 列表1将包含100,200 300
  • 列表2将包含400,200
  • 列表3将包含500

理想情况下,我希望它是单个LINQ语句。

3 个答案:

答案 0 :(得分:1)

尽管可行,但这是LINQ 的一个很好的例子。检查一下自己。

具有

var myList = new List<int> { 100, 200, 300, 400, 200, 500, };
int maxSum = 600;

&#34;纯&#34; LINQ(Aggregate的力量)

var result = myList.Aggregate(
    new { Sum = 0, List = new List<List<int>>() },
    (data, value) =>
    {
        int sum = data.Sum + value;
        if (data.List.Count > 0 && sum <= maxSum)
            data.List[data.List.Count - 1].Add(value);
        else
            data.List.Add(new List<int> { (sum = value) });
        return new { Sum = sum, List = data.List };
    },
    data => data.List)
    .ToList();

上述

的正常(非LINQ)实现
var result = new List<List<int>>();
int sum = 0;
foreach (var value in myList)
{
    if (result.Count > 0 && (sum += value) <= maxSum)
        result[result.Count - 1].Add(value);
    else
        result.Add(new List<int> { (sum = value) });
}

为了完整性(和一些乐趣),一个&#34; Hackish&#34; LINQ(闭包和C#运算符的强大功能)

int sum = 0, key = -1;
var result = myList.GroupBy(x => key >= 0 && (sum += x) <= maxSum ? key : ++key + (sum = x) * 0, (k, e) => e.ToList()).ToList();

答案 1 :(得分:0)

以下是您的问题的解决方案。我不确定这是否是最好的案例解决方案,但它肯定会完成这项工作:

List<int> First = myList.Where(x => x <= 300).ToList();
List<int> Second = myList.Where(x => x == 400 || x == 200).ToList();
List<int> Third = myList.Where(x => x == 500).ToList();

它通过列表进行查询并检查满足要求的值,然后将IEnumerable转换为List。

答案 2 :(得分:0)

这可以为任何大小的列表做你想要的,但可能没有你想要的那么短。你必须编写一个LINQ扩展方法来缩短它,但它会变得有点复杂。

List<int> myList = new List<int>();
myList.Add(100);
myList.Add(200);
myList.Add(300);
myList.Add(400);
myList.Add(200);
myList.Add(500);

var result = new List<List<int>>();
var skip = 0;
while (skip < myList.Count)
{
    var sum = 0;
    result.Add(myList.Skip(skip).TakeWhile(x =>
    {
        sum += x;
        return sum <= 600;
    }).ToList());
    skip += result.Last().Count();
}