2016-04-18 9 views
1

TL hinzugefügt oder entfernt Element finden) und sagen, welches Element geändert wird, während alle anderen Elemente übereinstimmen?Vergleicht man zwei Listen in einer von ihnen


Meine Klasse haben eine List<View> Eigenschaft, die von einem List<Model> über Konstruktor injiziert erstellt wird. Jede View umschließt ihre jeweilige Model als öffentliches Eigentum.

im gleichen Bereich, gibt es eine void Update(List<Model> newList) Routine, die eine weitere Liste von Model mit der folgenden Bedingung erhält: Es ist das gleiche wie vorher ist List<Model>, plus oder minus genau ein Element. Das liegt daran, dass Update jedes Mal aufgerufen wird, wenn ein Element an anderer Stelle einer datengebundenen Liste hinzugefügt oder daraus entfernt wird, und die Anwendung nur die Option zum Hinzufügen/Entfernen eines Elements auf einmal hat.

Die Motivation für den Update Betrieb, anstatt einfach die Modelle zu ersetzen (in Ansichten gewickelt) der alten Liste mit neuem, ist, dass View Klassen Speicher Zustand, so will ich ihr Modell ersetzen, sondern behalten ihre Zustand - der sowieso nicht in den Modellen gespeichert ist.

Das Problem ist: Ich muss neue Ansicht hinzufügen, wenn es ein neues Modell gibt, muss ich die jeweilige Ansicht entfernen, wenn das entsprechende Modell abwesend ist, und ich muss bereits vorhandene Ansichten mit ihren bereits vorhandenen Modellen, außer für das Element hinzugefügt oder entfernt. Ich bin mir nicht sicher, wie ich das machen soll.

Also habe ich darüber nachgedacht, das Modell im ersten Element der Liste mit dem ersten Element der neuen Liste zu vergleichen, und wenn sie übereinstimmen, dann gehe zum zweiten Element und so weiter. An einem Punkt werden sie sich unterscheiden, aber dies kann wegen der Hinzufügung eines Elements sein (und dann wird der Rest um einen Index verschoben), oder wegen der Entfernung eines Elements (in diesem Fall wird der Rest nach unten verschoben und das andere Element wird tatsächlich ein bereits vorhandenes Element in der Liste sein).

Gibt es eine vernünftige Möglichkeit festzustellen, ob das erste andere Element durch Hinzufügen oder Entfernen verursacht wird?

+0

, wie Sie vergleichen Ansichten mit Modellen? –

+0

Wenn vielleicht zuviel des Guten sein, aber Sie können versuchen, mit https://github.com/GregFinzer/Compare-Net-Objects –

+1

Klingt wie, was Sie das Gegenteil eines Intersect wollen, ist (scheinbar eine symmetrische Differenz genannt), beschrieben [hier] (http://stackoverflow.com/questions/5620266/the-opposite-of-intersect). Der Weg zu wissen, ob etwas eine Ergänzung oder Entfernung ist, ist herauszufinden, zu welcher der beiden Listen das unterschiedliche Modell gehört. Wenn es Teil des "Vorher" aber nicht des "Nachher" war, wurde es entfernt. Wenn es Teil des "Nachher" aber nicht des "Vorher" ist, wurde es hinzugefügt. –

Antwort

1

können Sie Except() Erweiterung verwenden, zum Beispiel:

List<Model> models = new List<Model>(); 
List<View> views = new List<View>(); 

Dann können Sie die gewünschte hinzugefügt/entfernt Element dies zu tun bekommen:

//If models.Count > views.Count 
var addedModel = models.Except(views.Select(v => v.Model)).FirstOrDefault(); 

//If views.Count > models.Count 
var modelToRemove = views.Select(v => v.Model).Except(models).FirstOrDefault(); 
var viewToRemove = views.Single(v => v.Model == modelToRemove); 

Vielleicht benötigen Sie einen IEqualityComparer<Model> für Gewohnheit führen Vergleich.


Wenn die Listen sind oder können nach einigen Kriterien sortiert werden, können Sie tun, was Sie in der Frage gesagt, den Index finden, wo die Listen unterscheidet: Dann bekommen

//for simplicity sorts the lists according to some 'Id' 
models.Sort((a, b) => a.Id.CompareTo(b.Id)); 
views.Sort((a, b) => a.Model.Id.CompareTo(b.Model.Id)); 

den Index die Werte zu vergleichen: kann

var index = Enumerable.Range(0, Math.Min(models.Count, views.Count)) 
         .First(i => !Model.Equals(models[i], views[i].Model)); 

//If models.Count > views.Count 
var addedModel = models[index]; 

//If views.Count > models.Count 
var viewToRemove = views[index]; 
0

Es ist ganz einfach, wenn Sie eine Aktion Zustand hinzufügen {None, hinzugefügt, aktualisiert, gelöscht} zu Ihrem View Artikel wie diese

View 
{ 
    ActionState State{get;set;} 
} 

und dann können Sie aus Ihrer Eingabeliste abfragen, wie diese

var changedElement= views.FirstOrDefault(x=> x.State != ActionState.None); 

Als nächstes, abhängig von der Aktion können Sie hinzufügen/aktualisieren/entfernen Sie die jeweilige Ansicht aus der vorhandenen Liste, die Sie haben.

Hoffe diese Hilfe.

1

Nicht die kürzeste Lösung in Bezug auf die Codezeilen, aber wenn es, dass nicht mehr als einzelne Element bekannt sein Inserter oder zu einem Zeitpunkt (aber mehr als einzelne Änderung in ganzer Liste) entfernen Sie die folgende Schleife verwenden können:

var i = 0; 
var j = 0; 

while(i < oldList.Count || j < newList.Count) 
{ 
    if (i >= oldList.Count) 
    { 
     for(; j < newList.Count; j++) 
     { 
      Console.WriteLine("{0} added", newList[j]); 
     } 
     break; 
    } 
    if (j >= newList.Count) 
    { 
     for(; i < oldList.Count; i++) 
     { 
      Console.WriteLine("{0} removed", oldList[i]); 
     } 
     break; 
    } 

    if (oldList[i] == newList[j]) 
    { 
     Console.WriteLine("{0} not changed", oldList[i]); 
     i++; 
     j++; 
    } 
    else if(j < (newList.Count - 1) && oldList[i] == newList[j+1]) 
    { 
     Console.WriteLine("{0} added", newList[j]); 
     j++; 
    } 
    else 
    { 
     Console.WriteLine("{0} removed", oldList[i]); 
     i++; 

    } 
} 

denke ich, hat es folgende Vorteile gegenüber Except Lösung:

  • Kann mehr als eine Änderung finden
  • O (n + m) max Komplexizität
  • Mehr Kontrolle in Bezug auf, wie Sie Änderungen finden: Except Lösung kann nur Gleichheit prüfen, aber hier können Sie überprüfen wenn einige Modell-Eigenschaften, während andere geändert nicht