如何在linq中使用where子句和sum子句?

时间:2015-09-28 18:14:59

标签: c# .net linq

我想从价格表中获取一个列表,其中值的总和等于我想要的值。 让我用例子来解释。

List<int> prices= new List{ 1, 2, 3, 4, 5 };
List<int> filteredList = GetSumList(4); // get list where the sum equals to 4, 1-3 or just 4. it doesn't matter which one.

如何编写GetSumList(int sum)函数。

2 个答案:

答案 0 :(得分:1)

如果请求的总和不会那么大;并且所有项目都是正面的(允许为零),并且您不太关心内存,您可以使用以下方法:

public static IEnumerable<int> GetSumList(this IEnumerable<int> values, int sum) {
    List<int>[] sets = new List<int>[sum+1];
    sets[0] = new List<int>();
    foreach(int xi in values) { //O(N*sum*N) with N the number of items
        List<int> f0, f1, f2;
        for(int i = sum-xi; i >= 0; i--) { //O(N*sum)
            f0 = sets[i];
            f1 = sets[i+xi];
            if(f0 != null && (f1 == null || f0.Count < f1.Count-1)) {
                f2 = new List<int>(f0);//make clone, O(N)
                f2.Add(xi);
                sets[i+xi] = f2;
            }
        }
    }
    return sets[sum];
}

(如果不存在这样的总和,则返回null;此算法还将返回最小子集(如果有)。

该算法使用动态编程并考虑列表。每个都有一个不同的总和。如果在计算临时值时使用链接列表而不是List<int>,则可以更快地执行此操作,因为这允许(共享)克隆和插入头部中的O(1 )。

演示(使用csharp交互式shell):

csharp> List<int> prices= new List<int>(new int[] { 1, 2, 3, 4, 5 }); 
csharp> prices.GetSumList(4);                                                              
{ 4 }
csharp> prices.GetSumList(6); 
{ 2, 4 }
csharp> prices.GetSumList(7); 
{ 3, 4 }
csharp> prices.GetSumList(8); 
{ 3, 5 }
csharp> prices.GetSumList(9); 
{ 4, 5 }
csharp> prices.GetSumList(10);
{ 2, 3, 5 }
csharp> prices.GetSumList(11); 
{ 2, 4, 5 }
csharp> prices.GetSumList(12); 
{ 3, 4, 5 }
csharp> prices.GetSumList(13); 
{ 1, 3, 4, 5 }
csharp> prices.GetSumList(14); 
{ 2, 3, 4, 5 }
csharp> prices.GetSumList(15); 
{ 1, 2, 3, 4, 5 }
csharp> prices.GetSumList(16); 
null

答案 1 :(得分:0)

如果你有列表列表,你可以做一个非常简单的LINQ扩展方法。

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;


public class Test
{
    public static void Main()
    {
        var lists = new List<List<int>>
        {
            new List<int> { 1, 2, 3 }, // 6
            new List<int> { 3 }, // 3
            new List<int> { 3, 3 }, // 6
            new List<int> { 1, 2 }, // 3
            new List<int> { 6 } // 6
        };

        Console.WriteLine(lists.GetSumList(6).Count); // 3
    }
}

public static class ListHelpers
{
    public static List<List<int>> GetSumList(this List<List<int>> list, int sum)
    {
        return list.Where(x => x.Sum() == sum).ToList();
    }
}