2010-09-10 10 views
11

İki listemiz var, diyelim ki öğrenciler ve puanları. Bu iki listeyi karşılaştırmak ve yeni liste ile eski liste arasındaki deltayı bulmak, daha sonra yeni listeye Ekle veya Güncelle'ye ilişkin en az müdahaleci yolu bulmak. Bu yaklaşım için en iyi algoritma nedir? Yeni listeye ve performansa minimum düzeyde değişiklik yapmak istiyorum.İki listeyi karşılaştırmak ve bu iki liste arasındaki deltayı bulmak için en etkili model/algoritma hangisidir?

örnek kod:

List<ListItem> existingList = new List<ListItem>(); 
List<ListItem> newList = new List<ListItem>(); 

public TopLists() 
{ 
    InitTwoLists(); 
} 

private void InitTwoLists() 
{ 
    existingList.Add(new ListItem { Name = "Shane", Score = 100 }); 
    existingList.Add(new ListItem { Name = "Mark", Score = 95 }); 
    existingList.Add(new ListItem { Name = "Shane", Score = 94 }); 
    existingList.Add(new ListItem { Name = "Steve", Score = 90 }); 
    existingList.Add(new ListItem { Name = "Brian", Score = 85 }); 
    existingList.Add(new ListItem { Name = "Craig", Score = 85 }); 
    existingList.Add(new ListItem { Name = "John", Score = 82 }); 
    existingList.Add(new ListItem { Name = "Steve", Score = 81 }); 
    existingList.Add(new ListItem { Name = "Philip", Score = 79 }); 
    existingList.Add(new ListItem { Name = "Peter", Score = 70 }); 

    newList.Add(new ListItem { Name = "Shane", Score = 100 }); 
    newList.Add(new ListItem { Name = "Steve", Score = 96 }); // This is change 
    newList.Add(new ListItem { Name = "Mark", Score = 95 }); 
    newList.Add(new ListItem { Name = "Shane", Score = 94 }); 
    newList.Add(new ListItem { Name = "Brian", Score = 85 }); 
    newList.Add(new ListItem { Name = "Craig", Score = 85 }); 
    newList.Add(new ListItem { Name = "John", Score = 82 }); 
    newList.Add(new ListItem { Name = "Steve", Score = 81 }); 
    newList.Add(new ListItem { Name = "Philip", Score = 79 }); 
    newList.Add(new ListItem { Name = "Peter", Score = 70 }); 
} 
} 

public void CompareLists() 
{ 
    // How would I find the deltas and update the new list with any changes from old? 
} 
} 

public class ListItem 
{ 
    public string Name { get; set; } 
    public int Score { get; set; } 
} 

** DÜZENLEME: İstenen çıkış ***

istenen çıkış aslında delta ile newlist değiştirmektir. bu senaryoda Örneğin:

newList.Add(new ListItem { Name = "Shane", Score = 100 }); 
    newList.Add(new ListItem { Name = "Steve", Score = 96 }); // This is change 
    newList.Add(new ListItem { Name = "Mark", Score = 95 }); 
    newList.Add(new ListItem { Name = "Shane", Score = 94 }); 
    newList.Add(new ListItem { Name = "Brian", Score = 85 }); 
    newList.Add(new ListItem { Name = "Craig", Score = 85 }); 
    newList.Add(new ListItem { Name = "John", Score = 82 }); 
    newList.Add(new ListItem { Name = "Steve", Score = 81 }); 
    newList.Add(new ListItem { Name = "Roger", Score = 80 }); // Roger is a new entry 
    newList.Add(new ListItem { Name = "Phillip", Score = 79 }); // Philip moved down one 

// Peter Ben sadece ilk 10

istiyorum çünkü Yani değişiklikler olacağını, 70 onun puanıyla bu listeyi devre dışı bırakır:

Güncelleme rekor 2 "Steve" için puanı Linq kullanabilir miyim kapalı üst 10.

+0

genel bir çözüm mü arıyorsunuz? Veya listelerin belirli bir sıralama düzeni gibi belirli kısıtlamalar var mı? –

+0

Listelerin büyüklükte aynı olacağını varsayalım mı? Ayrıca A listesinde yer alan ve B listesinde olmayan ve tersini de bulmak ister misiniz? –

+0

genel çözüm. Listeler her zaman eşit olur. Sıralama düzeni, her zaman azalan puanın bir türüdür. – Shane

cevap

4

ait "Peter" için pozisyon 9 Damla kayıtlarına "Roger" takın yeni rekor değişti:

Belirli
List<ListItem> list1 = GetYourList1(); 
List<ListItem> list2 = GetYourList2(); 
var diff = list1.Except(list2); 

Sizin örnek: en verimli ama özlü :) eğer

var diff = newList.Except(existingList); 

emin değil

+5

Ancak OP, mevcut bir çözüm değil ** bir algoritma ** istiyor. – Oded

+1

Bunu denemeniz gerekebilir, teoride çalışmalı, ancak pratikte, ListItem'in eşitlik karşılaştırmasını nasıl uyguladığına bağlı olacaktır. Bir Öğrenci sınıfı oluşturmak ve Eşittir seçeneğini geçersiz kılmak için daha iyi olabilir. –

+1

Liste2'deki ancak liste1 olmayan öğeler nasıl olur? Bu şekilde sadece yeni eklenen unsurları algıladığımı düşünüyorum. Ayrıca, IEquatable 'arayüzüne uygun bir uygulama uygulamanız da gerekir. –

3

sonra, genel, dil-agnostik çözüm arıyorsanız eğer Sipariş listelerinin bir çeşit data synchronization modelini arıyoruz. Temel algoritma olacaktır: Eğer listesinde iki kere aynı adı yoksa

i1 = 0 
i2 = 0 
while (i1 < list1.size && i2 < list2.size) 
{ 
    if (list1[i1] < list2[i2]) 
    { 
    //list1[i1] is not in list2 
    i1++ 
    } 
    else if (list1[i1] > list2[i2]) 
    { 
    //list2[i2] is not in list1 
    i2++ 
    } 
    else 
    { 
    //item is in both lists 
    i1++ 
    i2++ 
    } 
} 
if (i1 < list1.size) 
    //all remaining list1 items are not in list2 
if (i2 < list2.size) 
    //all remaining list2 items are not in list1 
+0

Bu, sıralı bir liste farklılığı yerine ayarlanmış bir farklılığa (sıralanmış bir listeye göre) benziyor: Sipariş bilgilerini kaybedersiniz. – Demurgos

2

Bu hile yapmak gerekir. Örneğinizde, 2x Steve'iniz var, ancak aralarında ayrım yapmak için bir yola ihtiyacınız var.

public static List<ListItem> CompareLists(List<ListItem> existingList, List<ListItem> newList) 
{ 
    List<ListItem> mergedList = new List<ListItem>(); 
    mergedList.AddRange(newList); 
    mergedList.AddRange(existingList.Except(newList, new ListItemComparer())); 
    return mergedList.OrderByDescending(x => x.Score).Take(10).ToList(); 
} 

public class ListItemComparer : IEqualityComparer<ListItem> 
{ 
    public bool Equals(ListItem x, ListItem y) 
    { 
     return x.Name == y.Name; 
    } 

    public int GetHashCode(ListItem obj) 
    { 
     return obj.Name.GetHashCode(); 
    } 
} 

Böyle diyebilirsin:

newList = CompareLists(existingList, newList); 
İlgili konular