2010-12-28 8 views
52

IEnumerable<T>'u LINQ ve yalnızca tek bir sorgu/LINQ ifadesi kullanarak iki IEnumerable<T>'a bölebilir miyim?Bir IEnumerable'ı iki sorguda olmaksızın bir boole ölçütü tarafından ikiye bölebilir miyim?

IEnumerable<T> üzerinden iki kez yinelemekten kaçınmak istiyorum. Örneğin, son iki ifadeyi aşağıdaki şekilde birleştirmek mümkün mü, bu nedenle allValues ​​yalnızca bir kez değiştirilir mi?

var groups = allValues.GroupBy(val => val.SomeProp); 

senin örneğinde olduğu gibi acil olarak değerlendirilmesi zorlamak için::

IEnumerable<MyObj> allValues = ... 
List<MyObj> trues = allValues.Where(val => val.SomeProp).ToList(); 
List<MyObj> falses = allValues.Where(val => !val.SomeProp).ToList(); 

cevap

52

Bu kullanabilirsiniz Sözlükler gibi

var groups = allValues.GroupBy(val => val.SomeProp) 
         .ToDictionary(g => g.Key, g => g.ToList()); 
List<MyObj> trues = groups[true]; 
List<MyObj> falses = groups[false]; 
+1

zarif! Anahtarın eksik olduğu durumu işlemek için groups.ContainsKey() veya groups.TryGetValue() yöntemini her zaman kullanabilirim. – SFun28

+3

Bir anahtar (true veya false) kullanılmazsa, bu kilitlenir. Örneğin. SomeProp her zaman doğruysa, gruplar [false] istisna ile çarpılır "Verilen anahtar sözlüğe eklenmedi" – buffjape

+0

GroupBy grupları oluşturmak için sıralama kullanın. Tarama işleminin iki kez yinelenmesi daha iyi bir şey yapıp yapmayacağımı bilmiyorum. – ejmarino

48

Bazı insanlar, ama nedeniyle davranışına Lookups tercih zaman anahtar eksik.

Maalesef, bu yaklaşım iki kez listeleniyor - bir kez aramayı oluşturmak için listeler oluşturun. Gerçekten listeleri gerekmiyorsa

, tek yineleme için bu aşağı alabilirsiniz:

IEnumerable<MyObj> trues = theLookup[true]; 
IEnumerable<MyObj> falses = theLookup[false]; 
+4

+1 Araması önerme ve Sözlük kullanılırken eksik tuşlarla ilgili olası sorun hakkında bilgi almak için. –

+0

İkinci grupta gruplamanın IEnumerable olması gerektiğini düşünüyorum? Gruplama, derleme yapmıyor ve GroupBy uzantı yönteminin bir sonucu gibi görünüyor. Ya da belki de IGrouping için bir döküm gerekli? – SFun28

+0

Ben de ToLookup'u tercih ederim. – leppie

3

Kopya makarna uzatma yöntemi size kolaylık sağlamak için. C#

public static void Fork<T>(
    this IEnumerable<T> source, 
    Func<T, bool> pred, 
    out IEnumerable<T> matches, 
    out IEnumerable<T> nonMatches) 
{ 
    var groupedByMatching = source.ToLookup(pred); 
    matches = groupedByMatching[true]; 
    nonMatches = groupedByMatching[false]; 
} 

Ya kullanarak tuples 7,0

public static (IEnumerable<T> matches, IEnumerable<T> nonMatches) Fork<T>(
    this IEnumerable<T> source, 
    Func<T, bool> pred) 
{ 
    var groupedByMatching = source.ToLookup(pred); 
    return (groupedByMatching[true], groupedByMatching[false]); 
} 

// Ex. 
var numbers = new [] { 1, 2, 3, 4, 5, 6, 7, 8 }; 
var (numbersLessThanEqualFour, numbersMoreThanFour) = numbers.Fork(x => x <= 4); 
İlgili konular