2012-03-12 18 views
11

Sorumun en önemli kısmı atlamadır. Yaklaşık 20 elemente sahip bir enum türünü kullanmayı planlıyorum. Bu set boyunca yinelemek istiyorum ama her seferinde bir eleman veya iki atlamak gerekiyor. Atlamak için ne önceden bilinir. Benzer bir örnek, alfabenin tüm harflerini içeren enum türüdür ve yinelemede, tüm ünlüleri atlamak istiyorum.Bazı değerleri atlarken enum türüyle nasıl yineleme yapılır?

nasıl zarif/verimli bir şekilde iterasyon kod gerekir? Ünlülerden oluşan ayrı bir eleman seti yapmalı mıyım? Gösterilecek kodum yok çünkü sorun hakkında düşünüyorum.

cevap

27
var query = Enum.GetValues(typeof(MyEnum)) 
    .Cast<MyEnum>() 
    .Except(new MyEnum[] { MyEnum.A, MyEnum.E }); 
foreach (MyEnum item in query) { 
    ... 
} 

Sen LINQ sihirli almak için döküm gerekir. Except tek başına bunu yapmayacaktır.


GÜNCELLEME:

bir fikrim daha var. Sen FlagsAttribute ile enum tanımlamak ve 2'nin güçler olarak düzenli değerlerini tanımlayabilir, en kolay bitsel kaydırılmasıyla elde ne operatörü << bıraktı. C# 7.0 ile başlayarak, 0b_0000_0000_0010_0000 gibi ikili değişmezleri de kullanabilirsiniz. Daha sonra mevcut değerleri yeni değerler oluşturmak için birleştirmek mümkündür.

[Flags] 
enum MyEnum 
{ 
    None = 0, 
    A = 1 << 0, 
    B = 1 << 1, 
    C = 1 << 2, 
    D = 1 << 3, 
    E = 1 << 4, 
    ... 
    X = 1 << 23, 
    Y = 1 << 24, 
    Z = 1 << 25, 
    Vowels = A | E | I | O | U 
} 

Şimdi, tek bir bitsel VE-çalışmasıyla testini gerçekleştirebileceği, birinci çözümün üzerinde avantajdır bu

IEnumerable<MyEnum> query = Enum.GetValues(typeof(MyEnum)) 
    .Cast<MyEnum>() 
    .Where(x => (x & MyEnum.Vowels) == MyEnum.None); 
foreach (MyEnum item in query) { 
    ... 
} 

benzeri bir sorgu formüle edebilirsiniz.

İkide 32 güçlere tanımlayabilirsiniz. Eğer daha fazla gerekiyorsa, long olarak enum taban türünü tanımlamak ve 64 bayrak değerlerinin (artı mevcut bayrak değerlerinin kombinasyonları) kadar kullanabilirsiniz.

[Flags] 
enum MyEnum : long 
{ 
    ... 
} 
+0

Bu muhtemelen en eksiksiz yanıttır. Buradan yapılacak en kolay şey, kurtulacaksın bu atlama koleksiyonları sahip olabilir ve dışında istediğimi kriterler içinde geçebilir bu şekilde atlamak isteyeyim numaralamalar çeşitli koleksiyonları belirtmektir. – SPFiredrake

+0

Evet ve çeşitli sorguları da tutabilirsiniz. –

+1

Testi yapmak için sadece bir bitsel AND kullanarak başka bir çözüm daha ekledim. Olağanüstü değerler için diziler veya HashSets gerektirmez. Lütfen güncellemeye bakın. –

1

Ben ünlülerin oluşan elemanların ayrı bir set yapın ve ardından LINQ kullanarak iki takım arasındaki kümesi farkı alacaktı. Bir aracılığıyla atlamak/tüm değerleri almak için, daha sonra tutmak için hangi değerlerin ifade

int[] vowels = {Letters.A, Letters.E, Letters.I, Letters.O, Letters.U}; 
IEnumerable<int> consonant = Enum.GetValues(typeof(Letters)).Except(vowels); 
foreach (int consonant in consonants) 
{ 
    // Do something with each consonant 
} 
1

ben muhtemelen sadece LINQ kullanmak istiyorum - - Enum.GetValues kullanmak (yazdığım bir tip-güvenli jenerik enum/temsilci kütüphane veya Unconstrained Melody kullanın) Where yan tümce.

Yalnızca belirli değerleri atlıyorsanız, bir HashSet veya benzeri bir şey yararlı olabilir (yalnızca birini atlıyorsanız buna değmez) - bir koşula göre atlama yapıyorsanız, o zaman -blown yüklemi çağrılır. Örneğin

:

public static IEnumerable<T> AllBut(T skipped) where T : struct 
{ 
    IEqualityComparer<T> comparer = EqualityComparer<T>.Default; 
    return AllBut<T>(t => !comparer.Equals(skipped, t)); 
} 

public static IEnumerable<T> AllBut(Func<T, bool> skipPredicate) where T : struct 
{ 
    IEqualityComparer<T> comparer = EqualityComparer<T>.Default; 
    return Enum.GetValues(typeof(T)) 
       .Cast<T>() 
       .Where(t => skipPredicate(t)); 
} 
İlgili konular