2016-11-02 26 views
15

Soru: verilen IEnumerable<>, hangi sıralamanın x öğesinden daha fazlasını içerdiğini nasıl kontrol edilir? Optimize LINQ Sayısı()> X


MCVE

:

static void Main(string[] args) 
{ 
    var test = Test().Where(o => o > 2 && o < 6); // ToList() 
    if (test.Count() > 1) // how to optimize this? 
     foreach (var t in test) // consumer 
      Console.WriteLine(t); 
} 

static IEnumerable<int> Test() 
{ 
    for (int i = 0; i < 10; i++) 
     yield return i; 
} 

Buradaki sorun Count() tam dizisini çalışacak budur ve bu 1E6 + öğe (ToList() da kötü bir fikir) bulunuyor. Ayrıca tüketici kodunu değiştirmemize izin verilmiyor (tam diziyi kabul eden bir yöntem). büyüktest koleksiyonu (Count()pahalı olduğunda), tipik bir hile deneyebilirsiniz durumunda

+1

olacaktır: posta bir yöntemde yılında böyle bir hile isteyebilir, EnsureCount demek? – Pikoh

+1

'Any()' kesinlikle iyi olmalı mı? Count(), bir dizinin herhangi bir öğe içerip içermediğini belirleyen "Any" ifadesinin aksine tüm koleksiyonu toplar. – Ric

+0

@Pikoh, kötüyüm, 'Any()', 'item()' koşullarına uyan ilk öğeye kadar sırayla koşuyordu. Evet, 'Any()' x = 1' olduğunda durumu gösterir. – Sinatr

cevap

18

:

if (test.Skip(1).Any()) 

test.Count() > x

if (test.Skip(x).Any()) 
içine tekrar yazılabilir genel durumda

Edit: siz

public static partial class EnumerableExtensions { 
    public static IEnumerable<T> EnsureCount<T>(this IEnumerable<T> source, int count) { 
     if (null == source) 
     throw new ArgumentNullException("source"); 

     if (count <= 0) 
     foreach (var item in source) 
      yield return item; 
     else { 
     List<T> buffer = new List<T>(count); 

     foreach (var item in source) { 
      if (buffer == null) 
      yield return item; 
      else { 
      buffer.Add(item); 

      if (buffer.Count >= count) { 
       foreach (var x in buffer) 
       yield return x; 

       buffer = null; 
      } 
      } 
     } 
     } 
    } 
    } 

ve böylece kodu nedir `Any` hakkında

var test = Test() 
    .Where(o => o > 2 && o < 6) 
    .EnsureCount(2); // <- Count() > 1, so at least 2 items 

    foreach (var t in test) 
    Console.WriteLine(t); 
+2

Bu oldukça zekice! – n8wrl

+0

Koleksiyonun 1 maddeye sahip olması durumunda bu başarısız olur ... '.Skip (-1)' çalışırdı ama bu 'hile' nin nasıl çalıştığını anlamıyorum. – Phill

+0

@Phill: beklenen davranış: kod, test.Dount()> 1 'optimize etmeyi dener, lütfen dikkat edin>> '' '' = = '. –