VisualBasic Bestimmte Daten aus zwei verschiedenen Dateien vergleichen

Scindapsus

Cadet 3rd Year
Registriert
März 2011
Beiträge
58
Hallo Programmiererfahrene,

für meine Frage folgender Hintergrund:
Ich soll ein Programm mit grafischer Oberfläche erstellen, welches zwei Dateien einliest, ausgibt und vergleicht.
Das Einlesen und die Ausgabe stellen kein Problem dar, aber am Vergleich scheitere ich.
Für den Vergleich gilt:
  • Datei1 beinhaltet alle personenbezogenen Daten (wie bspw. Name)
  • Datei2 beinhaltet eine Liste mit personenbezogenen Daten (wie bspw. Name)
  • Der Vergleich soll ermitteln welche Namen in Datei1 vorkommen, aber in Datei2 fehlen

Als Beispiel:
Datei1
Anton
Berta
Cäsar
Dora
Emil

Datei2
Anton
Cäsar
Emil

Ergebnis des Vergleichs:
Es fehlen Berta, Dora

Wie ist das in Visual Basic zu realisieren?

Vielen Dank für eure Antworten!
 
Zuletzt bearbeitet:
Theoretisch macht es ja keinen Unterschied, welche Datei 1 ist und welche Datei 2.
Das heißt, ich muss so oder so die eine Datei nach den Einträgen der anderen Datei durchsuchen.

Also einfach über die Einträge der einen Datei laufen und immer abgleichen, ob er mit einem Eintrag in der anderen Datei übereinstimmt, wenn ja, kannst du den Eintrag vergessen. Die Einträge, die du nach dem Durchlaufen auf der Merkliste hast, fehlen also in der anderen Datei.
Et voila.

Programmieren musst du selbst, wir sind kein Hausaufgabenforum ;)
 
Folgendes löst das Problem (Kurzfassung):


Dim namenAusDatei1 As New List(Of String) From {"Anton", "Berta", "Cäsar", "Dora", "Emil"}
Dim namenAusDatei2 As New List(Of String) From {"Anton", "Cäsar", "Emil"}

Dim fehlendeNamen As New List(Of String)
fehlendeNamen = (
From namen As String
In namenAusDatei1
Where Not namenAusDatei2.Contains(namen)
Select namen
).ToList

For Each item In fehlendeNamen
Messagebox.show(item)
Next


Problem ist für mich gelöst! :)
 
naja nicht wirklich gelöst ...
du willst die datein doch einlesen ....

also wer das format der datei interessant
wenn in jeder zeile ein neuer name ist einfach beide files in strings laden und einen split auf vbCrLf durchführen
dann einfach beide datein miteinander durch 2 for schleifen vergleichen
 
Hallo InEv1L,

beim Einlesen der csv-Datei hatte ich vor meiner Fragestellung schon kein Problem. ;)
Ich lese die Datei wie folgt ein (man beachte, dass ich eine grafische Oberfläche kreieren sollte):

'Es handelt sich hier um den Auszug btn_Ausgabe_Alle_Click
Dim datei1 As String = "xyz.csv"
'Überprüfe. ob die Datei existiert
'- wenn ja, gebe sie in der Listview aus
'- wenn nein, zeige einen Hinweis an

If File.Exists(datei1) Then
Dim fs1 As New FileStream("xyz.csv", FileMode.Open)
Dim sr1 As New StreamReader(fs1)
Dim zeileDateiEins, teilDateiEins(), nameDateiEins As String
Dim namenAusDatei1 As New List(Of String)

'Label, welches Hinweise bzw. Fehler anzeigt, leeren
lbl_Hinweis.Text = ""
'List(of String) leeren, da sie sich sonst bei jedem Click auf den Button vergrößert
namenAusDatei1.Clear()
'Datei zeilenweise einlesen
Do Until sr1.Peek() = -1
zeileDateiEins = sr1.ReadLine()
'die Zeile anhand des Semikolons splitten
teilDateiEins = zeileDateiEins.Split(";")
'die gewünschten, gesplitteten Daten auf die Variable nameDateiEins bringen,
'um sie später in der Listview Spalte 1 anzuzeigen

nameDateiEins = teilDateiEins(1) & ", " & teilDateiEins(0)
'die gewünschten, gesplitteten Daten in die List(Of Sting) bringen
'um sie später in der Listview Spalte 0 anzuzeigen und
'um sie über den Button "Vergleich durchführen" verwenden zu können

namenAusDatei1.Add(teilDateiEins(2))
'Ausgabe der gewünschten Daten in der Lisview
With lview_AusgabeAlle.Items
Dim item As ListViewItem
item = .Add(teilDateiEins(2))
item.SubItems.Add(nameDateiEins)
End With
Loop
sr1.Close()
Else
lbl_Hinweis.Text = "Die Datei xyz.csv " & vbCrLf & "exitiert nicht!"
End If


Hilft dir das weiter?
 
Zuletzt bearbeitet:
Wenn es nur ein paar Einträge sind, dann sollte deine Lösung ausreichend schnell sein, jedoch bei mehreren 1000 Einträgen wirds ein Performance-Killer. Ich hätte es wahrscheinlich mit einem Dictionary (Hashtable) gelöst:

Code:
  Public Function CompareNames(ByVal sFile1 As String, ByVal sFile2 As String) As String()
    ' Einlesen der Namen aus der 1. CSV Datei
    Dim haNames1 As New System.Collections.Generic.Dictionary(Of String, Boolean)(1000)
    For Each sLine As String In System.IO.File.ReadAllLines(sFile1)
      Dim sName As String = sLine.Split(";")(1)
      haNames1(sName) = True
    Next
    ' Namen aus der 2. CSV Datei mit der 1. CSV Datei vergleichen
    Dim listMissingNames As New System.Collections.Generic.List(Of String)
    For Each sLine As String In System.IO.File.ReadAllLines(sFile2)
      Dim sName As String = sLine.Split(";")(1)
      If Not haNames1.ContainsKey(sName) Then
        listMissingNames.Add(sName)
      End If
    Next
    '
    ' in listMissingNames stehen nun die Namen, die in der 1. CSV Datei fehlten
    '
    Return listMissingNames.ToArray()
  End Function

Das Durchsuchen bei einer Liste bedeutet, dass von Anfang bis zum gesuchten Element die Liste durchlaufen wird und bei jeder Position eine Prüfung erfolgt, ob es das ist, was man sucht. Wenn also ein Name nicht in der Liste ist (der Worst-Case), wird die gesamte Liste durchlaufen. Bei großen Listen werden sehr viele Durchläufe notwendig, die nunmal das Programm "bremsen". Das passiert jedoch im Hintergrund im .Net Framework bei Verwendung der Contains() Methode einer Liste.

Im Gegensatz dazu wird bei einer Hashtable die genaue Position eines möglichen Eintrags errechnet und dann an dieser Position geschaut, ob auch tatsächlich das Element an dieser Stelle vorhanden ist. Das ist für große Listen schneller...
 
Zuletzt bearbeitet: (Fehlerteufel hatte zugeschlagen)
Danke für den Hinweis Rossibaer,
aber meine Liste beinhaltet maximal 150 Zeilen, sodass die Anzeige des Vergleichs völlig ausreichend binnen 1 Sekunde aktualisiert wird.

Dein Quellecode beachtet halt nicht, dass ich eine grafische Oberfläche kreieren sollte (was wohl daran liegt, dass du nur das Relevante posten wolltest) --> erst Datei1 einlesen und ausgeben, dann Datei2 einlesen und ausgeben und schließlich den Vergleich durchführen.

Wenn ich dich zitieren darf
in listMissingNames stehen nun die Namen, die in der 1. CSV Datei fehlten
- ich benötige die Namen die in der 2. csv-Datei im Vergleich zur 1. csv-Datei (welche alle Namen enthält) fehlen.
Stellt aer kein Problem dar, da man deinen Code ja individuell anpassen kann.

Da ich ein Anfänger in Visual Basic bin, werde ich aus Übungszwecken deine Variante trotzdem mal auf mein - bereits gelöstes - Problem anwenden. Eine Hastabelle kannte ich bis Dato nicht, aber so wie du schreibst, bringt mir die sehr viel. ;)
Deine Erklärung
Im Gegensatz dazu wird bei einer Hashtable die genaue Position eines möglichen Eintrags errechnet und dann an dieser Position geschaut, ob auch tatsächlich das Element an dieser Stelle vorhanden ist. Das ist in für große Listen schneller...
klingt gut.
 
Ich bin mal so frech und zitiere dich auch ;)

Dein Quellecode beachtet halt nicht, dass ich eine grafische Oberfläche kreieren sollte (was wohl daran liegt, dass du nur das Relevante posten wolltest) --> erst Datei1 einlesen und ausgeben, dann Datei2 einlesen und ausgeben und schließlich den Vergleich durchführen.

Hey, wo bleibt da der Lerneffekt, wenn ich dir dein Programm schreibe und du nur noch Copy & Paste machst? ;) Viel Spaß beim Anpassen, verlieren kann man dabei eh nicht, nur an Erfahrung gewinnen...

- ich benötige die Namen die in der 2. csv-Datei im Vergleich zur 1. csv-Datei (welche alle Namen enthält) fehlen.
Stellt aer kein Problem dar, da man deinen Code ja individuell anpassen kann.

einfach die Datei-Parameter vertauschen und schon hast du deine gewünschte Variante, d.h. Suche der in CSV 2 fehlenden Namen.

Also viel Spaß und Erfolg.
Rossibaer
 
und was is das problem 2 arrays miteinander zu vergleichen ?

Code:
For a As Interger = 0 to Datei1.length()
      Dim vorgekommen As Boolean = False
      For b As Interger = 0 to Datei2.length()
            If Datei1(a) = Datei2(b) Then
                vorgekommen = True
                Exit For
            End If           
      Next
      If vorgekommen = False Then
         item = .Add(Datei1(a))
      End If
Next

Hoff ich habs ned falsch verstanden ....
 
Hallo Scindapsus,

ich sitze vor einem ähnlichen Problem, allerdings geht es bei meinen Listen nicht um Namen, sondern um Dateien. Ich habe Deine Lösung ausprobiert, jedoch kann ich keinen Vergleich durchführen. Kannst Du mir sagen, woran das liegen könnte? Wie Du nutze ich eine List (of String), was da für Informationen in den Strings stehen, sollte ja egal sein.

Gruß
Martin
 
kommt ja auch drauf an, was du in der Liste stehen hast... vielleicht mal rein-debuggen und wirklich nachschauen...
 
DUbuggen was das denn ???

wenn du 2 unterschiedliche werte vergleichst kommt ein False raus von daher ...
mehr sag ich dazu nicht
 
Wie müsste ich mein Programm anpassen, wenn Datei1 neben den Namen auch noch den Ort beinhaltet, also bspw.
Anton; Berlin
Berta; Köln
Cäsar; Stuttgart
Dora; Dresden
Emil; Mainz

Datei2 beinhaltet nach wie vor nur die Namen, also bspw.
Berta
Cäsar

Ergebnis des Vergleichs sollen diesmal aber nicht die fehlenden Namen, sondern deren Orte sein, d.h.
Es fehlen
Berlin
Dresden
Mainz

Ist das möglich, wenn ja, wie?
 

Ähnliche Themen

Zurück
Oben