Could C# Linq do combinatorics?

2020-05-11 10:16发布

I have this data structure:

class Product
{
    public string Name { get; set; }
    public int Count { get; set; }
}

var list = new List<Product>(){ { Name = "Book", Count = 40}, { Name = "Car", Count = 70}, { Name = "Pen", Count = 60}........... } // 500 product object


var productsUpTo100SumCountPropert = list.Where(.....) ????

// productsUpTo100SumCountPropert output:
// { { Name = "Book", Count = 40}, { Name = "Pen", Count = 60} }

I want to sum the Count properties of the collection and return only products objects where that property Count sum is less than or equal to 100.

If is not possible with linq, what is a better approach that I can use?

标签: c# linq lambda
3条回答
Fickle 薄情
2楼-- · 2020-05-11 10:43

You need the Count extension method

list.Count(p => p.Count <= 100);

EDIT:

If you want the sum of the items, Where and Sum extension methods could be utilized:

list.Where(p => p.Count <= 100).Sum(p => p.Count);
查看更多
劳资没心,怎么记你
3楼-- · 2020-05-11 11:04

Judging from the comments you've left on other peoples' answers and your gist (link), it looks like what you're trying to solve is in fact the Knapsack Problem - in particular, the 0/1 Knapsack Problem (link).

The Wikipedia page on this topic (that I linked to) has a short dynamic programming solution for you. It has pseudo-polynomial running time ("pseudo" because the complexity depends on the capacity you choose for your knapsack (W).

A good preprocessing step to take before running the algorithm is to find the greatest common denominator (GCD) of all of your item weights (w_i) and then divide it out of each value.

d <- GCD({w_1, w_2, ..., w_N})
w_i' <- w_i / d //for each i = 1, 2, ..., N
W' <- W / d //integer division here

Then solve the problem using the modified weights and capacity instead (w_i' and W').

The greedy algorithm you use in your gist won't work very well. This better algorithm is simple enough that it's worth implementing.

查看更多
三岁会撩人
4楼-- · 2020-05-11 11:05
list.Where(p=> p.Count <= 100).ToList();
查看更多
登录 后发表回答