2009-07-04 4 views
1

kann jemand helfen, ich habe Probleme, eine Sortierung, ich dachte, ich hatte es sortiert, aber scheint nicht zu funktionieren.Problem mit benutzerdefinierten IComparer für Liste (sort) - C#

Ich habe eine Liste, die speichert die folgenden Werte

8,6,10,11,7

Ich habe auch eine andere Liste (Zubehör in meiner Klasse und es hat eine propert accessoryId Strom die Klassen genannt sind in der Reihenfolge der ID, die aktuell ist 6,7,8,10,11)

Daher muss ich sie von 6,7,8,10,11 nach der Reihenfolge aus der einfachen Liste, die 8 ist zu sortieren , 6,10,11,7

Ich habe meine icomparable (siehe unten) und ich rufe so - es gelangt aber etwas falsch ist, weil die Liste immer noch alle meine Klassen hat, aber immer noch in der Größenordnung von 6,7,8,10,11

// accesories is the IList<Accessories> (hence why i am use ToList) 
    // and sortOrder is the simple int list list<int> 
    accesories.ToList().Sort(new ItemTpComparer(sortOrder)); 

class ItemTpComparer : IComparer<Accessories> 
{ 
    private IList<int> otherList; 

    public ItemTpComparer(IList<int> otherList) 
    { 
     this.otherList = otherList; 
    } 

    #region IComparer<Accessories> Members 

    public int Compare(Accessories x, Accessories y) 
    { 

     if (otherList.IndexOf(x.AccessoryId) > otherList.IndexOf(y.AccessoryId)) 
      return 1; 

     else if (otherList.IndexOf(x.AccessoryId) < otherList.IndexOf(y.AccessoryId)) 
      return -1; 
     else 
      return 0; 

     // tried below also didn't work 
     //return otherList.IndexOf(x.AccessoryId) - otherList.IndexOf(y.AccessoryId); 

Antwort

9

Der Vergleich korrekt ist (auch die kommentierten einzelne Zeilenversion) ist . Das Problem ist ToList() erstellt eine neue List mit einer Kopie der Elemente in der IEnumerable<T> Objekt, so im Grunde, erstellen Sie eine neue Liste, sortieren und wegwerfen.

var sortedList = accesories.ToList(); 
sortedList.Sort(new ItemTpComparer(sortOrder)); 

, für die würde ich vorschlagen, mit dem Ersetzen:

var sortedList = accessories.OrderBy(sortOrder.IndexOf).ToList(); 

diese Weise kein Vergleich Umsetzung erforderlich wäre. Sie können auch sortieren in absteigender Reihenfolge leicht:

var sortedList = accessories.OrderByDescending(sortOrder.IndexOf).ToList(); 

Wenn das Objekt wirklich List<Accessories> ist, könnte man es auch an Ort und Stelle sortieren:

((List<Accessories>)accessories).Sort(new ItemTpComparer(sortOrder)); 
+0

Wow! Danke das ist wirklich gut .. ich habe "var sortedList = accesories.OrderBy (item => sortOrder.IndexOf (item.AccessoryId)). ToList();" Auch wenn ich weniger Nummern sortiere, zB sortiere ich 8,6 .. und sortiere .. es funktioniert was toll ist .. was passiert ist das die 8,6 am Ende der Ergebnisse sortiert wird ... ist es möglich um am Anfang 8,6 zu sortieren und dann weil es keine Sorten mehr gibt. Den Rest in die Reihenfolge am Ende legen? –

+0

@mark smith: Das liegt daran, dass 'IndexOf' -1 für nicht existierende Objekte zurückgibt. Ich aktualisiere die Antwort für die absteigende Sortierung. –

+0

Ein großes Dankeschön ... Fixed! –

1

Mehrdad Sie zeigte, warum die Liste nicht sortiert wurde. Ich möchte die Leistung des Vergleichers und auch das Problem mit weniger sortierten Artikeln als sortierten Artikeln ansprechen.

Die Verwendung von IndexOf in einer Liste, um den Index zu finden, ist ziemlich ineffizient. Ich muss die Elemente in der Liste durchlaufen, um die richtige zu finden. Verwenden Sie ein Wörterbuch als Lookup statt, auf diese Weise nur eine Schleife durch die Elemente einmal:

class ItemTpComparer : IComparer<Accessories> { 

    private Dictionary<int, int> index; 

    public ItemTpComparer(IList<int> otherList) { 
     index = new Dictionary<int, int>(); 
     for (int i = 0; i < otherList.Count; i++) { 
     index.Add(otherList[i], i); 
     } 
    } 

    public int Compare(Accessories x, Accessories y) { 
     return index[x.AccessoryId].CompareTo(index[y.AccessoryId]); 
    } 

} 

Wenn Sie die Liste der Wert zulassen möchten sortiert werden, dass sie kürzer als die Liste der Elemente zu sortieren, können Sie überprüfen, ob der Wert existiert im Wörterbuch:

public int Compare(Accessories x, Accessories y) { 
     int xIndex, yIndex; 
     if (!index.TryGetValue(x.AccessoryId, out xIndex)) xIndex = int.MaxValue; 
     if (!index.TryGetValue(y.AccessoryId, out yIndex)) yIndex = int.MaxValue; 
     return xIndex.CompareTo(yIndex); 
    } 
+0

Vielen Dank ... sehr geschätzt, ich habe es notiert .. es kann nützlich sein, aber momentan benutze ich das Lambda-Zeug, da ich es auch lernen muss :-). Aber danke –

+0

Beachten Sie, dass die Lambda-Lösung das gleiche Leistungsproblem hat, es sei denn, Sie erstellen ein Indexwörterbuch und verwenden anstelle des IndexOf ... – Guffa

Verwandte Themen