2015-10-16 8 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 सूची मान शामिल हैं और तालिका आईडी के साथ तुलना करें।

इस के बाद की उम्मीद परिणाम

kid - 001 
kid - 004 

मैं नीचे क्वेरी करने की कोशिश की है:

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

लेकिन उस रिटर्न सभी मिलते-जुलते बच्चा, यहां तक ​​कि एकल मैच तो वे कहते हैं कि परिणाम देते हैं, लेकिन मैं केवल उन लोगों को चाहता हूं जो सभी तालिका आईडी से मेल खाते हैं। और मेरी क्वेरी के परिणाम

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

कृपया इस के लिए एक LINQ क्वेरी का सुझाव है।

+0

क्या LINQ आवश्यक है? मैं एसक्यूएल क्वेरी के साथ समाधान दे सकता हूं। – niksofteng

+0

नहीं, मैं इसे LINQ – ADMIN

+0

में चाहता हूं शायद यह [intersect] (http://stackoverflow.com/a/7565274/1257607) उत्तर मदद कर सकता है – DanielV

उत्तर

1

आदेश प्राप्त करने के लिए आप क्या चाहते हैं में की तरह है GroupKid करके अपने मान:

Klist.GroupBy(k => k.Kid) 

परिणाम उनकी संगत Tableid रों साथ अलग Kid रों की एक सूची है।

इसके बाद, हमें उन समूहों का चयन करने की आवश्यकता है जिनके लिए उनके सभी Tableid एस tid एस के समान हैं। यह Except के साथ दोनों सूचियों के समान तत्वों को हटाकर हासिल किया जा सकता है। फिर हम जांचते हैं कि कोई शेष तत्व नहीं है (यानी दोनों सेट बराबर हैं)।

:

.Select(g => g.Key); 

हम सब कुछ एक साथ इकट्ठा, तो हम निम्न LINQ क्वेरी मिलती है:

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

अंत में, समूह शेष हैं, जो समूह में Key के रूप में जमा है Kid मिल

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

तत्वों को वापस करने 001 और 004

1

आप समूह kList पहले, तो tid साथ SequenceEqual उपयोग कर सकते हैं, यहाँ एक डेमो

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 चाहते हैं, तो आप के लिए Intersect उपयोग कर सकते हैं SequenceEqual की instand, कोड, आपको पहले की जरूरत इस

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 मान चाहते हैं जब यह पंक्तियों में 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 है।

संबंधित मुद्दे