Laden...

2 Listen miteinander vergleichen

Erstellt von SteelWarrior vor 16 Jahren Letzter Beitrag vor 16 Jahren 6.790 Views
SteelWarrior Themenstarter:in
99 Beiträge seit 2006
vor 16 Jahren
2 Listen miteinander vergleichen

Hallo,

Ich habe ein Problem bei der Implementierung eines Vergleich zweier Listen.

  1. Ich habe mir zwei Listen generiert, die die selbe Item-Objekt haben.
  2. Es sollen hier die Listen nicht sortiert werden, da sie schon mit dem Parameter Id von 0 ... 254 sortiert aufglistet werden (IComparable macht hier kein Sinn)
  3. Beim Vergleichen der Ids der Items sollen nur die aItem.Id=1 und bItem.Id=1 abgearbeitet werden, wie kann ich vermeiden aItem.Id=1 und bItem.Id=2 zu vergleichen.

Ich wäre für jede Hilfe dankbar.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace CompareList
{
    public partial class Form1 : Form
    {
        List<Item> aItems = new List<Item>();
        List<Item> bItems = new List<Item>();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnAddList_Click(object sender, EventArgs e)
        {
            //..... Durch eine andere Funktion werden beide Listen wie folgt befüllt...

            // 1. Liste
            Item aItem = new Item();
            aItems.Add(aItem);
            aItem.Id = 0;
            aItem.Name = "Marc";
            aItems.Add(aItem);
            aItem.Id = 1;
            aItem.Name = "Dani";
            aItems.Add(aItem);
            aItem.Id = 2;
            aItem.Name = "Mike";
            aItems.Add(aItem);
            aItem.Id = 3;
            aItem.Name = "Tom";
            aItems.Add(aItem);
            aItem.Id = 4;
            aItem.Name = "Gollum";

            // 2.Liste
            Item bItem = new Item();
            bItems.Add(bItem);
            bItem.Id = 0;
            bItem.Name = "Marc";
            bItems.Add(bItem);
            bItem.Id = 1;
            bItem.Name = "Dani";
            bItems.Add(bItem);
            bItem.Id = 2;
            bItem.Name = "Hans"; // Name ist Hans
            bItems.Add(bItem);
            bItem.Id = 3;
            bItem.Name = "Sally"; // Name ist Sally
            // bItem.Id=4 fehlt
        }

        private void btnCompare_Click(object sender, EventArgs e)
        {
            // Definition für die Errors
            // aItem.Name == bItem.Name (Item.Error = 0)
            // aItem.Name != bItem.Name (Item.Error = 1)
            // aItem nicht vorhanden (Item.Error = 2)
            // bItem nicht vorhanden (Item.Error = 3)
            // gibt es weitere Möglichkeiten??

            foreach (Item aItem in aItems) 
            {
              foreach (Item bItem in bItems) 
              {
                  if(aItem.Id == bItem.Id)
                  {
                     if(aItem.Name == bItem.Name)
                     {
                        aItem.Error = 0;
                        bItem.Error = 0;
                     }
                     else if(aItem.Name != bItem.Name)
                     {
                        aItem.Error = 1;
                        bItem.Error = 1;
                     }
                  }
                  else if(aItem.Id != bItem.Id) //hier entsteht ein Fehler bei bItem.Id=4, weil es       nicht vorhanden ist , wie könnte man dies umgehen?
                  {
                        aItem.Error = 3;
                        bItem.Error = 3;

                  }
               }
            }
        }
    }

    public class Item
    {
        private int m_Id;
        private string m_Name;
        private int m_Error;

        public int Id
        {
            get
            {
                return m_Id;
            }
            set
            {
                if (m_Id != value)
                {
                    m_Id = value;
                }
            }
        }

        public string Name
        {
            get
            {
                return m_Name;
            }
            set
            {
                if (m_Name != value)
                {
                    m_Name = value;
                }
            }
        }

        public int Error
        {
            get
            {
                return m_Error;
            }
            set
            {
                if (m_Error != value)
                {
                    m_Error = value;
                }
            }
        } 
    }
}

1. Googlen 2. Boardsuche benutzen 3. Überlegen 4. Posten

Ich sage es nur äußerst ungerne,aber darf man in Foren/wo auch immer eine klitzekleine Frage stellen,ohne dass gleich ein Oberlehrer mit der obligatorischen "Google suchen"-Antwort kommt?

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo SteelWarrior,

wie kann ich vermeiden aItem.Id=1 und bItem.Id=2 zu vergleichen.

gar nicht. Ohne die beiden Items zu vergleichen weißt du ja nicht, dass du sie nicht vergleichen willst. 🙂 Aber es schadet ja nicht, sie zu vergleichen. Wenn man sie nicht beachten will, tut man das eben aufrund des Ergebnis des Vergleich einfach nicht.

An deinem Code unten fehlt doch eigentlich nur noch das


foreach (Item aItem in aItems) {
   foreach (Item bItem in bItems) {
      // hier dein Vergleichs Code
   }
}

herbivore

S
1.047 Beiträge seit 2005
vor 16 Jahren

wie schauts damit aus?


public class Item {
    public int Id;
    public string Name;
    public int Error;

    public Item() {
        Id = -1;
        Name = String.Empty;
        Error = -1;
    }
}

bool foundId = false; //signalisiert ob ein bItem mit entsprechedner Id gefunden wurde

foreach(Item b in bItems) {
    b.Error = -1;
}

foreach(Item a in aItems) {
    foundId = false;
    foreach(Item b in bItems) {
        if(a.Id == b.Id) {
            foudId = true;
            if(a.Name == b.Name) {
                a.Error = 0;
                b.Error = 0;
            } else {
                a.Error = 1;
                b.Error = 1;
            }
            break;
        }
    }
    if(!foundId) {
        a.Error = 3;
    }
}
foreach(Item b in bItems) {
    if(b.Error == -1) {
        b.Error = 2;
    }
}

kurze erklärung:
also deine klasse item hab ich abgeändert so das error als initialwert -1 is, damit man später sieht ob da schon was geändert wurde

so, also beide leisten werden quasi durchgegangen wobei jedes item aus aItems mit jedem item aus bItems verglichen werden
wenn ein item mit derselben id gefunden wird, wird ein bollsche variable auf true gesetzt
das signalisiert ob es für ein item aus aItems auch ein item aus bItems gab (später wichtig)
vergleich von a und b ist ansonsten gleich wie bei dir geblieben, nur das ich danach die innere schleife abbreche, haben ja unser ergebnis
wenn jedes b aus bItems mit einem a verglichen wurde wird geprüft ob die boolsche variable true oder false is
ist sie false heißt das in bItems haben wir nichts gefunden mit der gleichen id, also setzen wir den errorcode in a auf 3
nachdem jedes item aus aItems abgearbeitet wurde, sollte für jedes item auch ein error code gesetzt sein
in bItems ist für jedes Item ein errorcode gesetzt wo entweder der name gleich war oder unterschiedlich, d.h. alle restlichen haben kein entsprechendes item in aItems
daher die 2. schleife die alle items in bItems durchgeht und prüft ob errorcode -1 is (der initialwert) und dafür dann eine 2 einträgt (a in aItems nicht vorhanden)

nachtrag:
da wir den errorcode von einem Item in bItems als indikator benutzen sollte nwir ihn vor dem ganzen geprüfe auc hwieder zurück setzn auf -1

is halt bissl unschön das wir 2x zusätzlich durch bItems durchlaufen müßen, aber wüßte jetzt auch nicht wie man das eleganter lösen könnten

nachtrag 2:
andere lösung die mir grad einfällt wäre das hier


Dictionary<int, Item> dic = new Dictionary<int, Item>(aItems.Length);
foreach(Item a in aItems) {
    a.Error = 3;
    dic.Add(a.Id,a);
}
foreach(Item b in bItems) {
    Item a = null;
    dic.TryGetValue(b.Id,out a);
    if(a != null) {
        if(a.Name == b.Name) {
            a.Error = 0;
            b.Error = 0;
        } else {
            a.Error = 1;
            b.Error = 1;
        }
    } else {
        b.Error = 2;
    }
}

wäre, schätz ich mal, halt bissl schneller, aber verbrauch bissl mehr speicherplatz
dafür mußt du deine klasse nicht anpassen 🙂

nachtrag: von hashtable auf dictionary umgestellt

SteelWarrior Themenstarter:in
99 Beiträge seit 2006
vor 16 Jahren

Danke sheitman,

die erste Lösung hat mir weitergeholfen 🙂

1. Googlen 2. Boardsuche benutzen 3. Überlegen 4. Posten

Ich sage es nur äußerst ungerne,aber darf man in Foren/wo auch immer eine klitzekleine Frage stellen,ohne dass gleich ein Oberlehrer mit der obligatorischen "Google suchen"-Antwort kommt?