2016-08-16 7 views
2

この複雑な状況にlinq解があるかどうかわかりません。たとえば、お客様はを選択します。色:赤、サイズ:大、タイプ:コットン私は、お客様がそれぞれの単一の時間これらのフィルタを選択することを確実に知るならば、私はちょうどこのようなものだろう。ここではLinqに基づく複合検索フィルタを構築する

var shirts = ListOfShirts.Where(i=> i.Color.Contains("red") && Size.Contains("Large") && Type.Contains("Cotton")); 

を現在の構造とビューからのフィルタの数を受け入れるアクションメソッドです。

クラス

public partial class Shirt { 
    public long ID { get; set; } 
    public string Color { get; set; } 
    public string Size { get; set; } 
    public string Type { get; set; } 
} 

public class SelectedFilter { 
    public string Name { get; set; } // Filter Menu Title 
    public string Value { get; set; } 
} 

コントローラー

public ActionResult Filter(IList<SelectedFilter> selectedFilters) { 
     var model = new List<Shirt>(); 
     Shirt ListOfShirts = db.GetAllShirts(); 
     var groups = selectedFilters.GroupBy(i => i.Name); 

      foreach (var g in groups) 
      { 
       var GroupName = g.FirstOrDefault().name; 
       var GroupValues = g.Select(i => i.value).ToList(); 

       if (g.FirstOrDefault().name == "Color") 
       { 
        model = ListOfShirts.Where(i => GroupValues.Contains(i.Color)).ToList(); 
       } 
       else if (g.FirstOrDefault().name == "Size") 
       { 
        model = ListOfShirts.Where(i => GroupValues.Contains(i.Size)).ToList(); 
       } 
       else if (g.FirstOrDefault().name == "Type") 
       { 
        model = ListOfShirts.Where(i => GroupValues.Contains(i.Type)).ToList(); 
       } 
      } 
    } 
+1

、基本的には、式をどのように構築しますその名前に基づいてプロパティにアクセスしますか? – Groo

+2

これを書くことなく、式ツリーを見てください:https://msdn.microsoft.com/en-us/library/mt654263.aspxこれを行うより洗練された方法の1つです。それ以外の場合は、where句で演繹的推論を実行してください。 – RandomUs1r

+0

*顧客が毎回これらのフィルタを選択することがわかっているなら、私はちょうどこのようなことをします* OK、何が問題なのですか?私は何かのように期待しています*しかし... * –

答えて

1

ワン(残忍な)方法は、それを行うには:あなたは、同じ名前を持つ複数のフィルタ値を持っている場合にも動作するはず

public ActionResult Filter(IList<SelectedFilter> selectedFilters) { 
     var model = new List<Shirt>(); 
     IEnumerable<Shirt> ListOfShirts = db.GetAllShirts(); 

     IEnumerable<Shirt> filteredListOfShirts = ListOfShirts 
      .Where(shirt => { 
       return (
        (selectedFilters.Any(filter => filter.Name == "Color" && !string.IsNullOrWhiteSpace(filter.Value)) ? // is Color filter set? 
         selectedFilters.Any(filter => 
         { 
          return (filter.Name == "Color" && shirt.Color == filter.Value); 
          }) : true) 
        && 
        (selectedFilters.Any(filter => filter.Name == "Size" && !string.IsNullOrWhiteSpace(filter.Value)) ? // is Size filter set? 
         selectedFilters.Any(filter => 
         { 
          return (filter.Name == "Size" && shirt.Size == filter.Value); 
         }) : true) 
        && 
        (selectedFilters.Any(filter => filter.Name == "Type" && !string.IsNullOrWhiteSpace(filter.Value)) ? // is Type filter set? 
         selectedFilters.Any(filter => 
         { 
          return (filter.Name == "Type" && shirt.Type == filter.Value); 
         }) : true) 
        ); 
       }); 

     model = filteredListOfShirts.ToList(); 

    } 

ご質問がある
{Name="Color",Value="Red"},{Name="Color",Value="Blue"} 
+1

ちょうどこのアプローチを試みるチャンスがあり、それは有望だった。ただし、同時に異なるフィルタに属する値を選択するとうまく機能しません。たとえば、カラーレッドを選択し、タイプコットンを選択すると、タイプコットンのみで終わるなど... – usefulBee

+1

コードを編集し、 "is filter set"の周りにかっこを追加しました。それがなければ、他のフィルターは検証されていないようだ。 – jtmnt

+0

編集したコードを試してみましたが、フィルタに関係なくすべての項目が返されているため動作していないようです。 – usefulBee

1

与えられたShirtがフィルタに含まれているかどうかを確認するメソッドを作成し、Allを使用してそれぞれを調べることができます。

public static void Filter(IList<SelectedFilter> selectedFilters) 
{ 
    var filters = selectedFilters 
     .GroupBy(i => i.Name); 

    var filteredShirts = db 
     .GetAllShirts() 
     .Where(shirt => filters.All(filter => ShirtInFilter(filter, shirt))); 
} 

public static bool ShirtInFilter(
    IGrouping<string, SelectedFilter> filter, 
    Shirt shirt) 
{ 
    var values = filter.Select(i => i.Value); 

    switch (filter.Key) 
    { 
     case "Color": 
      return values.Contains(shirt.Color); 
     case "Size": 
      return values.Contains(shirt.Size); 
     case "Type": 
      return values.Contains(shirt.Type); 
     default: 
      return false; 
    } 
} 

あなたはリフレクションを使用してプロパティにアクセスしたい場合switchをなくすことができ、それはあなたのユースケースのためにやり過ぎのように思えます。

+0

優れたアプローチとうまく動作します。しかし、私はそれをリダクティブフィルタリングの手法にするために調整する方法を知りましたか?カラーレッドとタイプコットンを選択すると、コットンタイプのレッドシャツのみが「唯一」になることを意味します。このアプローチはこれまで、すべての赤いシャツとタイプの綿のすべてのシャツをもたらします – usefulBee

+1

@ユーズドビーああ、私はあなたの質問を誤解しました。私の更新された答えに渦を吹き込み、あなたが必要とするものがあるかどうかを確認してください。 –

+0

私は更新された答えを確認し、それは魅力のように動作します!それは明確な理由から、別のアプローチへの答えを授与するのは難しい決定でした。しかし、私は本当に他の人とあなたの最高のノッチのスキルと4次元の心を共有していただきありがとうございます。止まらないでください! – usefulBee

関連する問題