简体   繁体   中英

How to filter a list by comparing a value from another list using Linq in C#?

I have a list of Fruit which has name and price value.

public class Fruit {
    public string name {get; set;}
    public int price {get; set;}

    public Fruit(string n, int p)
    {
            name = n;
            price = p;
    }
    ...
}

List<Fruit> myBasket = new List<Fruit>();
myBasket.Add(new Fruit("apple", 300));
myBasket.Add(new Fruit("banana", 200));
myBasket.Add(new Fruit("kiwi", 400));

Also, there is a list of average market price of fruits.

List<Fruit> averagePrice = new List<Fruit>();
averagePrice.Add(new Fruit("apple", 500));
averagePrice.Add(new Fruit("banana", 100));
averagePrice.Add(new Fruit("kiwi", 600));

What I want to do is to filter myBasket to have only fruit that is lower price than averagePrice.

So, in the example, myBasket will have apple and kiwi.

I tried myBasket = myBasket.Where(v => v.price < averagePrice.FirstOrDefault(y => y.name.Equals(v.name)).price).ToList(); .

It works well, but has a possibility of null pointer exception when there is new fruit in myBasket but not in averagePrice .

How can I change it to prevent it from exception?

Thanks in advance.

This seems to be quite a simple way to do it:

myBasket =
(
    from f in myBasket
    join a in averagePrice on f.name equals a.name
    where f.price < a.price
    select f
).ToList();

That gives me:

在此处输入图像描述


Here's the equivalent method-syntax:

myBasket =
    myBasket
        .Join(averagePrice, f => f.name, a => a.name, (f, a) => new { f, a })
        .Where(x => x.f.price < x.a.price)
        .Select(x => x.f)
        .ToList();

Comprehension query syntax

Func<Fruit, bool> take = (fruit) =>
{
  var query = averagePrice.Where(f => f.name == fruit.name);
  return query.Count() == 0 ? true : fruit.price <= query.Min(f => f.price);
};

var result = from fruit in myBasket
             where take(fruit)
             orderby fruit.name
             select fruit;

foreach ( var item in result )
  Console.WriteLine($"{item.name}: {item.price}");

For each fruit in the basket we search it in the average list and take the minimum price available to compare it.

It may be possible to optimize this query with advanced functions like joins and projections or other...

Output

apple: 300
kiwi: 400

Output without average banana

apple: 300
banana: 200
kiwi: 400

Lambda query version

var result = myBasket.Where(fruit =>
{
  var query = averagePrice.Where(f => f.name == fruit.name);
  return query.Count() == 0 ? true : fruit.price <= query.Min(f => f.price);
});

foreach ( var item in result.OrderBy(f => f.name) )
  Console.WriteLine($"{item.name}: {item.price}");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM