2016-04-08 26 views
3

Benim modeldir başka List tarafından bir Liste : Sıralama <T>

class Person 
{ 
    public int Id {get; set; } 
    public string Name {get; set; } 
} 

İki koleksiyonları var.

var orderedByIdList = tobeSortedList.OrderBy(x => etalonList.IndexOf(x.Id)); 

Ama böyle bir hata tanıştım: denedim

List<Person> etalonList = new List<Person>() 
{ 
    new Person() { Id=10, Name="Jon"}, 
    new Person() { Id=4, Name="Ben"}, 
    new Person() { Id=11, Name="Magnus"}, 
    new Person() { Id=8, Name="Joseph"}, 
}; 

List<Person> toBeSortedList = new List<Person>() 
{ 
    new Person() { Id=11, Name="Magnus"}, 
    new Person() { Id=4, Name="Ben"},     
    new Person() { Id=10, Name="Jon"}, 
    new Person() { Id=8, Name="Joseph"}, 
}; 

: Ve toBeSortedListetalonList gibi sıralamak istiyorum

cannot convert from 'int' to 'SOConsoleApplication.Person'

Belki başka önerileriniz ?

int index; 
var etalonDictionary = etalonList.ToDictionary(k => k.Id, v => index++); 

Sonra sözlükten kimliği geri bulmak ve sıralama için kullanan:

İlk sırayla etalonList gelen bir sözlük yaratacak
+1

tobeSortedList.OrderBy (x => etalonList.IndexOf (x.Id)) ToList(): Burada

sonunda olmayan varolan öğeleri koyar LINQ olduğunu – CodeConstruct

+1

@CodeConstruct Bu da işe yaramıyor. –

+0

Bunu bir Sınıf (Kişisel) – CodeConstruct

cevap

3

tasnif hızlandırmak için

var sortedList = toBeSortedList.OrderBy(x => etalonDictionary[x.Id]).ToList(); 
+0

Yine de bir hash tablosu kullanıyorsanız, kolayca sıralamayı da önleyebilirsiniz. ToBeSortedList'ten bir sözlük oluşturun ve sonra 'etalonList.Select (p => dict [p.Id])' yi kullanın. – Joren

2

List.IndexOf alır argüman olarak nesne ve indeksini döndürür. Id olan int -value değerini geçiyorsunuz. Bu derleme değil.

Equals + GethashCode'u geçersiz kılabilir ve x.Id yerine x geçirebilirsiniz. Ama bu durumda List.FindIndex tercih ediyorum: Burada

var orderedByIdList = toBeSortedList 
    .OrderBy(x => etalonList.FindIndex(p => p.Id == x.Id)); 

IndexOf kullanmanızı sağlayan geçersiz kılma Equals yaklaşım:

class Person 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public override bool Equals(object obj) 
    { 
     if(ReferenceEquals(obj, this)) 
      return true; 
     Person other = obj as Person; 
     if (other == null) 
      return false; 
     return other.Id == this.Id; 
    } 

    public override int GetHashCode() 
    { 
     return Id; 
    } 
} 

Şimdi bu da çalışır:

var orderedByIdList = toBeSortedList 
    .OrderBy(x => etalonList.IndexOf(x)); 
1

tahmin ediyorum etalonList'daki bazı değerler toBeSortedList'da bulunmaz, çünkü diğer tüm durumlarda soru hiçbir anlam ifade etmez. e:

  1. toBeSortedList, etalonList ürününe dahil olmayan öğelere sahiptir. Bu durumda sorun daha az belirtilmiştir; Bu yeni liste üyelerini nasıl sipariş edersiniz?
  2. toBeSortedList tam aynı üyeleri etalonList sahiptir. Bu durumda etalonList'a dönün veya çoğaltın. toBeSortedList sipariş

Saf bir, ama basit yolu (I 1 mümkün olmadığını davayı varsayıyorum unutmayın) şudur:

static IEnumerable<T> OrderBy(this IEnumerable<T> list, IEnumerable<T> guideList) 
{ 
    foreach (var member in guideList) 
    { 
     if (toBeSortedList.Contains(member)) 
      yield return member; 
    } 
} 

var orderedList = toBeSortedList.OrderBy(etalonList).ToList(); 

tüm bu kuyu gerçekleştirmez ama listeleri ise çok uzun değil, yapmalı.

1

Bu durumda düzenli sıralamaya ihtiyacınız yoktur. Hedefle etalonu kolayca join yapabilir ve hedef öğeleri yansıtabilirsiniz.Etalon tüm hedefleri içermiyorsa, var olmayan öğeleri, sıralı olarak bazı ek siparişler uygulayarak sıralanmış sıralamanın başında veya sonunda birleştirebilirsiniz. Her iki durumda da hızlı bir O (N) zaman karmaşıklığı işlemi ile sonuçlanacaksınız. .;

var orderedByIdList = 
    (from a in etalonList join b in toBeSortedList on a.Id equals b.Id select b) 
    .Concat 
    (from a in toBeSortedList join b in etalonList on a.Id equals b.Id into b where !b.Any() select a) 
    .ToList(); 
1
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, IEnumerable<T> guide) { 
     var toBeSorted = new HashSet<T>(list); 
     return guide.Where(member => toBeSorted.Contains(member)); 
    }