1
var filterModel = new List<FilterModel>()
{
    new FilterModel {Price = 1},
    new FilterModel {Price = 1},                
    new FilterModel {Price = 15},
    new FilterModel {Price = 20},
    new FilterModel {Price = 410},
    new FilterModel {Price = 9511},
    new FilterModel {Price = 9511},
    new FilterModel {Price = 252},
    new FilterModel {Price = 555},
    new FilterModel {Price = 602}
};

var priceList = new List<PriceList>
{
    new PriceList{MinPrice = 0,MaxPrice = 30},
    new PriceList{MinPrice = 70,MaxPrice = 130},
    new PriceList{MinPrice = 200,MaxPrice = 250},
    new PriceList{MinPrice = 400,MaxPrice = 600},
    //etc.etc. continue...
};

I have 2 models. I'm trying to use LINQ. My code is working. What would be the shortest (cleanest) way to do this?

var newFilterModel = new List<FilterModel>();

foreach (var t in priceList)
{
    newFilterModel.AddRange(filterModel
                               .Where(x => x.Price > t.MinPrice && x.Price < t.MaxPrice)
                               .ToList());
}
var distinctNewFilterModel = newFilterModel.Select(p=>new { p.Price})
                                           .Distinct().ToList();
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
user3583183
  • 91
  • 1
  • 5
  • 1
    what you mean _shortes(cleanest) way_? – Grundy Jul 28 '15 at 12:57
  • No use foreach if its possible. – user3583183 Jul 28 '15 at 12:58
  • you can use [join clause](https://msdn.microsoft.com/en-us/library/bb311040.aspx) and [this](https://msdn.microsoft.com/en-us/library/bb882533.aspx) – Grundy Jul 28 '15 at 13:01
  • btw, now your `distinctNewFilterModel` is list of `int` do you want get list of `int` or list of `FilterModel`? – Grundy Jul 28 '15 at 13:04
  • Looks pretty short and clean to me. If you want to convert it to a single Linq statement look up `SelectMany` and try something yourself, coming back when you get stuck. You'll understand it better and be able to tweak it. – D Stanley Jul 28 '15 at 13:10
  • FYI a Linq statement will have a `SelectMany`, a `Distinct`, a `Select`, and a `ToList`. Not sure it will be any shorter or cleaner. – D Stanley Jul 28 '15 at 13:14
  • @Grundy : My distinctnewFilterModel is List. and when I try this code my model's items will be 1,15,20... So FilterModel – user3583183 Jul 28 '15 at 13:14
  • nope, you do `newFilterModel.Select(p=>new { p.Price})` that return `IEnumerable` so you select only `Price` and your `distinctNewFilterModel` at end is `List` or what type you use for `Price` – Grundy Jul 28 '15 at 13:16
  • oh! i missed that you create anonymouse type `new { p.Price}` but anyway this not equal `FilterModel` :-) – Grundy Jul 28 '15 at 13:17

2 Answers2

2

I don't know if this is short & clean enough for you, but...

var newFilterModel = filterModel
    // Select just the price
    .Select(f => f.Price)
    // Remove duplicates
    .Distinct()
    // Find prices in the price list
    .Where(price => priceList
        .FindIndex(p => p.MinPrice <= price && price <= p.MaxPrice) != -1)
    // Turn the price back into a FilterModel object
    .Select(price => new FilterModel { Price = price })
    // Turn the entire result into a new List<FilterModel>
    .ToList();

newFilterModel.ForEach(newF => Console.WriteLine(newF.Price));

Results:

1
15
20
410
555

If you were to implement IEquatable<> in your FilterModel class like this:

public class FilterModel : IEquatable<FilterModel>
{
    public int Price { get; set; }

    public bool Equals(FilterModel other)
    {
        //Check whether the compared object is null.
        if (ReferenceEquals(other, null)) return false;

        //Check whether the compared object references the same data.
        if (ReferenceEquals(this, other)) return true;

        //Check whether the products' properties are equal.
        return other.Price == Price;
    }

    public override int GetHashCode()
    {
        //Get hash code for the Price field.
        return Price.GetHashCode();
    }
}

Then your Linq statement gets shorter:

var newFilterModel = filterModel
    // Remove duplicates
    .Distinct()
    // Find prices in the price list
    .Where(filterPrice => priceList
        .FindIndex(price => price.MinPrice <= filterPrice.Price && filterPrice.Price <= price.MaxPrice) != -1)
    // Turn the entire result into a List<FilterModel>
    .ToList();

newFilterModel.ForEach(p => Console.WriteLine(p.Price));

Results:

1
15
20
410
555
Shar1er80
  • 9,001
  • 2
  • 20
  • 29
1

You can use cross join like this and get IEnumerable<FilterModel>

var distinctNewFilterModel = from filter in filterModel
                             from price in priceList
                             where filter.Price > price.MinPrice && filter.Price < price.MaxPrice
                             group filter by filter.Price into groupped
                             select groupped.First();

but not sure that this shortest and cleanest than you have

Grundy
  • 13,356
  • 3
  • 35
  • 55