2012-02-02 13 views
2

一般的なリストItemListListIDにはすべてItemIDsが含まれていない場合はリストから削除したいと考えています。LINQを使用してすべての項目が含まれていないリストから削除

私は、データの削減バージョンで、以下の説明ましょう:私は同様の質問をし

ListID  ItemID  

    2   1 
    2   2 
    2   3 
    2   4 
    4   1 
    4   2 
    4   3 
    4   4 

MaxItemID = 4 

ListID  ItemID  

    1   1  
    2   1 
    2   2 
    2   3 
    2   4 
    3   1 
    3   2 
    4   1 
    4   2 
    4   3 
    4   4 
    5   1 
    5   2 

そして、私はそれから出たいデータは次のようになります昨日はSQLだけに関連していて、Existsを使った答えが得られましたが、それ以来、項目の最大数が異なる可能性があることが発見されました。またlinqを使いたいと思います。私はdistinct().Count()のテクニックを使ってもうまくいくと思っていましたが、これまでのところ成功しておらず、もっとも効率的な方法ではないようです。

どうもありがとうございました

答えて

2
int distinctIDs = items.Select(x => x.ItemID).Distinct().Count(); 
var newList = items 
    .GroupBy(x => x.ListID) 
    .Where(x => x.Select(y=>y.ItemID).Distinct().Count() == distinctIDs) 
    .SelectMany(x => x.ToList()) 
    .ToList(); 
+0

これは優れたL.B. - 治療をします。ありがとうございました。 Rezaにもありがとう - あなたの答えは同様に働いたが、これは私が実装したものである。 –

2

を私はこれがあなたの目的であると思います:

var list = 
    ItemList 
    .GroupBy(p=>p.ListID) 
    .Where(p=>p.Distinct().Count()<MaxItemID) 
    .ToArray() 
+0

私は思う。(p => p.Distinct()。Count()== MaxItemID)は彼が何のためにいるのか! – Flowerking

+0

偉大な答えReza、ありがとう - これも同様に働いた。 Upvote ... –

0

は、LINQのバージョンのパフォーマンスについてコメントすることはできませんが、ここでのLINQと非LINQのソリューションは、

ですhth、
アラン

編集

サンプルデータにはlistId/ItemIdの重複が表示されますので、私は別のチェックを省略しましたが、必要に応じてlinqステートメントの最初の部分として使用します。

編集2

は、LINQのコードを更新しました。
非linqコードを更新していません。ただ、(同じ以前の場合は追加する前に確認するためにチェックして、サンプル入力ごとにソートされ、ListId、アイテムIDを前提としています。

[TestMethod] 
public void LinqVersion() { 

    Dictionary<int, List<ListItem>> found = new Dictionary<int, List<ListItem>>(); 

    var comparer = new ListItemEqualityComparer(); 

    var actual = Input.Distinct(comparer).GroupBy(lstItem => lstItem.ListId).Where(grp => grp.Count() == 4).SelectMany(grp => grp); 

    Assert.IsTrue(Expected.SequenceEqual(actual, comparer)); 

} 


[TestMethod] 
public void NoLinqVersion() { 

    Dictionary<int, List<ListItem>> found = new Dictionary<int, List<ListItem>>(); 

    foreach (var listItem in Input) { 
     AddItem(found, listItem.ListId, listItem); 
    } 

    var actual = new List<ListItem>(); 
    foreach (var pair in found) { 
     if (pair.Value.Count == 4) { 
      actual.AddRange(pair.Value); 
     } 
    } 

    Assert.IsTrue(Expected.SequenceEqual(actual, new ListItemEqualityComparer())); 

} 

    private static void AddItem(IDictionary<int, List<ListItem>> dictionary, int listId, ListItem listItem) { 
     if (!dictionary.ContainsKey(listId)) { 
      dictionary.Add(listId, new List<ListItem>()); 
     } 
     dictionary[listId].Add(listItem); 
    } 

    public class ListItem { 
     public int ListId { get; set; } 
     public int ItemId { get; set; } 
    } 

    public class ListItemEqualityComparer : IEqualityComparer<ListItem> { 
     public bool Equals(ListItem x, ListItem y) { 
      return x.ListId == y.ListId && x.ItemId == y.ItemId; 
     } 

     public int GetHashCode(ListItem obj) { 
      return obj.ListId^obj.ItemId; 
     } 
    } 

    public List<ListItem> Input = new List<ListItem>(){ 
     new ListItem{ ListId = 1 , ItemId = 1}, 
     new ListItem{ ListId = 2 , ItemId = 1}, 
     new ListItem{ ListId = 2 , ItemId = 2}, 
     new ListItem{ ListId = 2 , ItemId = 3}, 
     new ListItem{ ListId = 2 , ItemId = 4}, 
     new ListItem{ ListId = 3 , ItemId = 1}, 
     new ListItem{ ListId = 3 , ItemId = 2}, 
     new ListItem{ ListId = 4 , ItemId = 1}, 
     new ListItem{ ListId = 4 , ItemId = 2}, 
     new ListItem{ ListId = 4 , ItemId = 3}, 
     new ListItem{ ListId = 4 , ItemId = 4}, 
     new ListItem{ ListId = 5 , ItemId = 1}, 
     new ListItem{ ListId = 5 , ItemId = 2}, 
    }; 


    public List<ListItem> Expected = new List<ListItem>{ 
     new ListItem{ ListId = 2 , ItemId = 1}, 
     new ListItem{ ListId = 2 , ItemId = 2}, 
     new ListItem{ ListId = 2 , ItemId = 3}, 
     new ListItem{ ListId = 2 , ItemId = 4}, 
     new ListItem{ ListId = 4 , ItemId = 1}, 
     new ListItem{ ListId = 4 , ItemId = 2}, 
     new ListItem{ ListId = 4 , ItemId = 3}, 
     new ListItem{ ListId = 4 , ItemId = 4} 
    }; 
+0

'2 2'行を '2 3' –

+0

@ L.Bに置き換えた場合、Linqバージョンは機能しません。 dupsのために働かないだろうか? Distinct(comparer)を最初のlinq節として追加します(editで言及します)。一致するコードを更新しました – AlanT

2

のスクリーンショットをチェックし、これは動作します。この

var query = from baseItem in itemList 
    group baseItem by baseItem.ListID into gr 
    where gr.Count() == MaxItemID 
    join selectItem in itemList on gr.Key equals selectItem.ListID 
    select selectItem; 

var requiredList = query.ToList(); 

を試してみてください。enter image description here

編集

重複が許可されている場合、クエリは

var query = from item in itemList 
    group item by item.ListID into gr 
    where gr.Select(s=>s.ItemId).Distinct().Count() == MaxItemID 
    join i in itemList on gr.Key equals i.ListID 
    select i; 
+0

''新しいアイテム{ListID = 2、ItemID = 2} 'を '新しいアイテム{ListID = 2、ItemID = 3}'に置き換えても機能しません –

+0

@LB:ケースを更新しました。 OPは重複について何も言及しなかった。しかし、とにかく良い点は、それも覆いました。 –

関連する問題