2015-10-16 141 views
6

是否有可能只返回匹配的那些人全部列表值在LINQ這在LINQ中可能嗎?

我有一個表klist其中兩個欄:

Kid - Tableid 
001  1 
001  2 
002  1 
003  3 
004  1 
004  2 

和我有一個包含tid值的列表:

List<int> tid = new List<int>(); 
tid.Add(1); 
tid.Add(2); 

現在tid名單有1和2的值。

所以我的問題是,從klist表我只會得到那些kid其中包含所有tid列表值並與表id進行比較。

在此之後該預期的結果

kid - 001 
kid - 004 

我想下面的查詢:

var lb = Klist.Where(t => tid .Contains(t.Tableid)).Select(k => k.Kid).Distinct().ToList(); 

但返回所有符合條件的孩子,如果連一根火柴,然後他們給這一結果,但我只想要那些匹配tid列表的所有表id的人。我查詢的 而結果是

kid - 001 
kid - 002 
kid - 003 
kid - 004 

請提出一個LINQ查詢此。

+0

是LINQ必須的嗎?我可以給與SQL查詢解決方案。 – niksofteng

+0

不,我想在LINQ – ADMIN

+0

也許這[intersect](http://stackoverflow.com/a/7565274/1257607)答案可以幫助 – DanielV

回答

1

爲了達到你想要的,你首先需要Group你的價值觀通過Kid

Klist.GroupBy(k => k.Kid) 

結果是截然不同的Kid S的其相應的Tableid的List。

之後,我們需要選擇其所有Tableidtid相同的組。這可以通過從兩個列表中刪除相同的元素來實現,使用Except。然後我們檢查是否沒有剩餘元素(即兩個集合是相等的)。

.Where(g => tid.Except(g.Select(s => s.Tableid)).Count() == 0) 

最後,獲得剩餘的羣體,這是存儲爲Key組中的Kid

.Select(g => g.Key); 

如果我們組裝都在一起,我們得到以下LINQ查詢:

var lb = Klist.GroupBy(k => k.Kid).Where(g => tid.Except(g.Select(s => s.Tableid)).Count() == 0).Select(g => g.Key); 

返回元素001004

1

可以組kList第一,然後用SequenceEqualtid,這裏是一個演示

List<KeyValuePair<string, int>> kList = new List<KeyValuePair<string, int>>() 
{ 
    new KeyValuePair<string, int>("001",1), 
    new KeyValuePair<string, int>("001",2), 
    new KeyValuePair<string, int>("002",1), 
    new KeyValuePair<string, int>("003",3), 
    new KeyValuePair<string, int>("004",1), 
    new KeyValuePair<string, int>("004",2) 
}; 
List<int> tid = new List<int>() { 1, 2 }; 
var query = kList.GroupBy(i => i.Key) 
    .Where(g => g.Select(j => j.Value).Distinct().OrderBy(i => i).SequenceEqual(tid)) 
    .SelectMany(g => g.Select(x => x.Key)).Distinct(); 
Console.WriteLine(string.Join(",", query)); 

,也許SequenceEqual有一些問題,如果你想contains所有tid,不Equal,那麼你可以使用IntersectSequenceEqual,代碼是這樣的

List<KeyValuePair<string, int>> kList = new List<KeyValuePair<string, int>>() 
{ 
    new KeyValuePair<string, int>("001",1), 
    new KeyValuePair<string, int>("001",2), 
    new KeyValuePair<string, int>("002",1), 
    new KeyValuePair<string, int>("001",3),//special one 
    new KeyValuePair<string, int>("003",3), 
    new KeyValuePair<string, int>("004",1), 
    new KeyValuePair<string, int>("004",2) 
}; 
List<int> tid = new List<int>() { 1, 2 }; 
var query = kList.GroupBy(i => i.Key) 
    .Where(g => g.Select(j => j.Value).Distinct().Intersect(tid).Count()==tid.Count) 
    .SelectMany(g => g.Select(x => x.Key)).Distinct(); 
Console.WriteLine(string.Join(",", query)); 
0

這工作相當很好:

var kList = new [] 
{ 
    new { Kid = "001", Tableid = 1 }, 
    new { Kid = "001", Tableid = 2 }, 
    new { Kid = "002", Tableid = 1 }, 
    new { Kid = "003", Tableid = 3 }, 
    new { Kid = "004", Tableid = 1 }, 
    new { Kid = "004", Tableid = 2 }, 
}; 

var tid = new List<int>() { 1, 2, }; 

var lookup = kList.ToLookup(k => k.Tableid, k => k.Kid); 

這產生:

1 => "001", "002", "004" 
2 => "001", "004" 
3 => "003" 

var result = tid.Select(t => lookup[t]).Aggregate((ts0, ts1) => ts0.Intersect(ts1)); 

tid.Select(...)產生{ { "001", "002", "004" }, { "001", "004" } }Aggregate然後對這兩個的相交。

結果是:

001 
004 
0

另一種方式,你可以做到這一點:

var list = kList.GroupBy(x => x.Kid) 
      .Select(group => new 
      { 
       Kid = group.FirstOrDefault().Kid, 
       gtid = group.Select(groupItem => groupItem.Tableid).ToList() 
      }) 
      .Where(group => !group.gtid.Except(tid).Any() 
       && !tid.Except(group.gtid).Any()) 
      .Select(group => group.Kid); 

基本上像其他的解決方案,你組kList數據並創建與kid和一個新的列表一個Tableid的列表。然後通過比較Tableid的列表和tid(確保沒有列表項不在另一列表中,反之亦然)來過濾新列表。然後,除此之外,您選擇kid值。

0

有很多答案,Except(Func<T, bool>).Any()Except(Func<T, bool>).Count() == 0但這兩種組合看起來應該只是All(Func<T, bool>)

根據你的問題,你說只有當kid值存在於All行時,你只需要kid值。這是我的方式。

var lb = klist.GroupBy(lst => lst.Kid) 
       .Where(t => tid.All(td => t.Select(x => x.TableId).Contains(td))) 
       .Select(grp => grp.Key); 

將表分組成包含Kid的集合。然後過濾掉tid值不存在all的行。然後它爲這些組選擇密鑰Kid