2012-08-25 22 views
5

List<Foo> adlı bir listeniz olduğunu hayal edin. Bu FooA, FooB, FooC veya FooD olabilir, böyleceNasıl bir liste türüne göre sipariş verilir?

Foo, soyut sınıftır. Ve bu öğeleri List<T> için bir uzantıya sahip olmak istiyorum. Örneğin, içinde 9 elemanım varsa, örneğin,

.

Sipariş türüne göre sıralı olacaktır.

FooA, FooB, FooC, FooD, FooA, FooB, FooC, FooA, FooA 

Ben fonksiyonu bu durumda, IE de, belirttiğiniz sırayla sipariş edilebilir olduğunu çalışıyorum, bu oldu:

new[] { typeof(FooA), typeof(FooB), typeof(FooC), typeof(FooD) } 

ben don bu uzantıyı yaratmaya çalıştığını, ancak edildi hiçbir şey alamıyorum. Biraz yardım edebilir misin? Bunu LINQ ile başarabileceğimi tahmin ediyorum.

+0

Listede FooC yoksa veya FooA, FooB, FooC, FooC, FooC, FooD varsa, bunu nasıl sıralarsınız? Amaçlarınız için seçim sıralamalarını uyarlamanızı öneririm. – DarthVader

cevap

6

Sen grup türüne göre ürün, türüne göre sıralamak ve grupları serpiştirebilir:

var groups = items.GroupBy(x => x.GetType()) 
        .OrderBy(g => orderedTypes.IndexOf(g.Key)) 
        .ToList(); 

var result = groups.First().Interleave(groups.Skip(1).ToArray()); 

Interleave method from EvenMoreLINQ kullanarak.

foreach (var item in result) 
{ 
    Console.WriteLine(item.GetType()); 
} 

Çıktı:

FooA 
FooB 
FooC 
FooD 
FooA 
FooB 
FooC 
FooA 
FooA 
1

Grup türüne, ardından öğeler arasında döngü bir set her zaman ekleyin. Şunlar gibi:

+0

'sortArray' nedir? –

+0

@ L.B: Sıralama düzenini belirten 'Tür 'nesneleri dizisi. – Guffa

0

list, sınıflandırılması gereken öğeler topluluğudur.
pattern, belirli sırada öğelerden oluşan bir koleksiyonudur.
result, öğesinin pattern gereğince sipariş edilen bir koleksiyonudur.

var list = new List<Foo> { new FooA(), new FooB(), new FooC(), new FooA(), new FooC(), new FooA(), new FooD() }; 
var pattern = new Foo[] { new FooB(), new FooC(), new FooD(), new FooA() }; 

var result = list.OrderBy(p => p, new MyFooComparer(pattern)); 

arabirimini IComparer<> uygulayan bir sınıf MyFooComparer yoktur.
Karşılaştırma, pattern koleksiyonundaki her Foo öğesinin konumuna dayanır. pattern öğeleri , numaralı çoğaltılmış olmamalıdır ve her tür Foo'u içermelidir (en azından list'da kullanılanlar).
O (1) karmaşıklığına sahip olduğu için desen sırasını saklamak için Dictionary<> kullanıyorum.Sonra arama

public class MyFooComparer : IComparer<Foo> 
{ 
    private readonly Dictionary<Type, int> _pattern; 
    public MyFooComparer(IEnumerable<Foo> pattern) 
    { 
     _pattern = new Dictionary<Type, int>(); 
     int i = 0; 
     foreach (var foo in pattern) 
     { 
      _pattern.Add(foo.GetType(), i); 
      i++; 
     } 
    } 

    public int Compare(Foo x, Foo y) 
    { 
     var xVal = _pattern[x.GetType()]; 
     var yVal = _pattern[y.GetType()]; 
     return xVal.CompareTo(yVal); 
    } 
} 

: pattern göre

 foreach (var foo in result) 
     { 
      Console.WriteLine(foo.GetType().Name); 
     } 

, alırsınız:

FooB 
FooC 
FooC 
FooD 
FooA 
FooA 
FooA 

DÜZENLEME:

Uzatma List<Foo> için:

static class MyExtension 
{ 
    public static IEnumerable<Foo> OrderByFoo<T>(this List<Foo> list, IEnumerable<Foo> patern) 
    { 
     return list.OrderBy(p => p, new MyFooComparer(patern)); 
    } 
} 
İlgili konular