Autor Thema: Effektiver Datenabgleich  (Gelesen 3525 mal)

Offline skywook

  • Senior Mitglied
  • ****
  • Beiträge: 445
  • Ich liebe dieses Forum!
Effektiver Datenabgleich
« am: 25.02.19 - 10:17:38 »
Hallo,

ich müsste zwei Datenbestände vergleichen. Vielleicht habt ihr einen Tipp für mich.

Die Daten sind (beispielhaft) wie folgt aufgebaut:

[Produkt-A]
Inhalt A
Inhalt B
Inhalt C

[Produkt-B]
Inhalt A
Inhalt F

[Produkt-C]
Inhalt A
Inhalt C
Inhalt X
Inhalt Z

usw..

Würde die Daten in ein Array einlesen um diese dann mit dem Bestand des Vormonats zu vergleichen.

Folgende Idee:
Eindimensionaler Array, Aufbau wie folgt:
ProduktA#InhaltA
ProduktA#InhaltB
ProduktB#InhaltA
usw

Bei dieser Idee bin ich bei ca. 200.000 Dimensionen - eventuell ist dann die Verarbeitung zu langsam?

Der zweidimensionale Array fällt aus da die zweite Dimension nicht fest definiert werden kann (oder eventuell die zweite Dimension als Array).

Wäre hier eine Liste oder eine Klasse effektiver?

Offline Tode

  • Moderatoren
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 6.873
  • Geschlecht: Männlich
  • Geht nicht, gibt's (fast) nicht... *g*
Re: Effektiver Datenabgleich
« Antwort #1 am: 25.02.19 - 10:38:02 »
Ich würde mit Listen von Listen arbeiten, das dürfte Performancemässig am besten sein. Damit Du Dir nicht die FInger brichst, würde ich eine Klasse "ListEnhanced" definieren:

Code
Class ListEnhanced
    Public listContent List as Variant
    Sub New()

    End Sub

Und dann so:

Code
Dim listsEnhanced List as ListEnhanced

Forall ProduktName in .... '- irgendwie aufbauen
   If Not Iselement( listsEnhanced( ProduktName ) ) then
       Set listsEnhanced( ProduktName ) = New ListEnhanced
   End If
   Forall Inhalt in ...
       listsEnhanced( ProduktName ).listContent( Inhalt ) = Inhalt
   End Forall
End Forall

Damit kannst Du dann sehr schnell zwei Listen aus unterschiedlicher Herkunft vergleichen...

Der IsElement- Vergleich bei Listen ist saumässig schnell.
« Letzte Änderung: 25.02.19 - 10:39:36 von Tode »
Gruss
Torsten (Tode)

P.S.: Da mein Nickname immer mal wieder für Verwirrung sorgt: Tode hat NICHTS mit Tod zu tun. So klingt es einfach, wenn ein 2- Jähriger versucht "Torsten" zu sagen... das klingt dann so: "Tooode" (langes O, das r, s und n werden verschluckt, das t wird zum badischen d)

Offline Ralf_B

  • Aktives Mitglied
  • ***
  • Beiträge: 144
  • Geschlecht: Männlich
Re: Effektiver Datenabgleich
« Antwort #2 am: 25.02.19 - 16:51:53 »
Als ich mal vor diesem Problem stand, hab ich mal versucht eine Sortierung (shell sort) zu machen und dann zu vergleichen,
Das hab ich aber recht schnell wieder verworfen, weil das viel Speicher und Zeit gekostet hat.

Ich habe dann eindimensionale Array's aufgebaut (mit Redim) und dann, fast wie empfolen , mit ArrygetIndex vergleichen.
Das passte dann.

Viel Erfolg.
 

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Re: Effektiver Datenabgleich
« Antwort #3 am: 25.02.19 - 17:59:48 »
Listen sind Arrays eindeutig vorzuziehen, da die nahezu keine Größenbeschränkung kennen

Offline skywook

  • Senior Mitglied
  • ****
  • Beiträge: 445
  • Ich liebe dieses Forum!
Re: Effektiver Datenabgleich
« Antwort #4 am: 26.02.19 - 13:38:46 »
Funktioniert, ist wirklich super schnell.

Aber wie Frage ich dann den listContent ab?

Funktioniert das auch mit IsElement oder muss ich diesen mit einer Schleife durchlaufen?

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Re: Effektiver Datenabgleich
« Antwort #5 am: 26.02.19 - 14:39:21 »
Liste in Liste geht m.W. leider nicht, wenn das Listenelement ein Array ist, musst Du es wie ein Array behandeln (also z.B. durchlaufen).

Kannst aber auch das Array dann in eine Liste schreiben.
Code
Dim liste1 List As Variant
Dim liste2 List As Integer

liste1 ("xxx") = Split ("a,b,c", ",")

If Iselement (liste1 ("xxx")) Then
   Erase liste2
   Forall element In liste1 ("xxx")
      liste2 (element) = 1
   End Forall
   If Iselement (liste2 ("b")) Then
      'Eintrag b in liste1 ("xxx") gefunden
   End If
End If

Kommt drauf an, was Du konkret damit machen willst. Bei häufigen Suchen innerhalb des Array vielleicht sinnvoll

Offline Tode

  • Moderatoren
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 6.873
  • Geschlecht: Männlich
  • Geht nicht, gibt's (fast) nicht... *g*
Re: Effektiver Datenabgleich
« Antwort #6 am: 27.02.19 - 09:05:47 »
@skywook: Da die Member- Variable listContent public ist und auch wieder eine Liste, fragst Du die ganz normal ebenfalls mit IsElement ab:

Code
If IsElement( listsEnhanced( ProduktName ).listContent( Inhalt ) ) then
    '...gefunden
End If

oder wenn Du schon ein Objekt der Klasse ListEnhanced hast:

Code
If IsElement( myListEnhanced.listContent( Inhalt ) ) then
    '...gefunden
End If

@Peter: Deshalb ja die "Hilfsklasse", die ihrerseits eine Liste als Public Member- Variable hat... Damit kriegt man dann Listen in Listen.

Man könnte jetzt natürlich auch die Hilfsklasse erweitern um weitere Funktionen wie hasMember( ) und getMember() und addMember, dann spart man sich diese vielen Klammern und auch den direkt- Zugriff auf die Member- Variable:

Code
Class ListEnhanced
    Public listContent List as Variant
    Sub New()

    End Sub
    Function hasMember( strMember as String ) as Boolean
        hasMember = IsElement( Me.listContent( strMember ) )
    End Function
    Function getMember( strMember as String ) as Variant
        If Me.hasMember( strMember ) then
          getMember = Me.listContent( strMember )
        End If
    End Function
    Sub addMember( strMember as String, varValue as Variant )
        Me.listContent( strMember ) = varValue
    End Sub

Dann würde der obige Code so aussehen:

Code
If listsEnhanced( ProduktName ).hasMember( Inhalt ) then
    '...gefunden: vergleichen
    content = listsEnhanced( ProduktName ).getMember( Inhalt )
End If

'- oder

If myListEnhanced.hasMember( Inhalt ) then
    '...gefunden: vergleichen
    content = myListEnhanced.getMember( Inhalt )
End If




« Letzte Änderung: 27.02.19 - 09:15:42 von Tode »
Gruss
Torsten (Tode)

P.S.: Da mein Nickname immer mal wieder für Verwirrung sorgt: Tode hat NICHTS mit Tod zu tun. So klingt es einfach, wenn ein 2- Jähriger versucht "Torsten" zu sagen... das klingt dann so: "Tooode" (langes O, das r, s und n werden verschluckt, das t wird zum badischen d)

Offline Tode

  • Moderatoren
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 6.873
  • Geschlecht: Männlich
  • Geht nicht, gibt's (fast) nicht... *g*
Re: Effektiver Datenabgleich
« Antwort #7 am: 27.02.19 - 09:23:15 »
Und das kann man dann immer weiter spinnen... wie wäre es mit weiteren Management- Funktionen:

Code
Class ListEnhanced
    Private m_listContent List as Variant
    Private m_lngCount as Long
    Sub New()
        Me.m_lngCount = 0
    End Sub
    Function hasMember( strMember as String ) as Boolean
        hasMember = IsElement( Me.m_listContent ( strMember ) )
    End Function
    Function getMember( strMember as String ) as Variant
        If Me.hasMember( strMember ) then
          getMember = Me.m_listContent ( strMember )
        End If
    End Function
    Sub addMember( strMember as String, varValue as Variant )
        If not Me.hasMember( strMember ) then
            Me.m_lngCount = Me.m_lngCount + 1
        End If
        Me.m_listContent ( strMember ) = varValue
    End Sub
    Sub removeMember( strMember as String )
        If Me.hasMember( strMember ) then
          Me.m_lngCount = Me.m_lngCount - 1
          Erase Me.m_listContent( strMember )
        End If
    End Sub
    Sub removeAllMembers()
        Erase Me.m_listContent
        Me.m_lngCount = 0
    End Sub
    Public Property Get length as Long
        length = Me.m_lngCount
    End Property
    Public Property Get listContent as Variant
        listContent = Me.m_listContent
    End Property
    Public Property Get isEmpty as Boolean
        isEmpty = (Me.m_lngCount = 0)
    End Property
    

Hier muss jetzt die Member- Variable für die Liste Private sein, damit sie nicht mehr von außen manipuliert werden kann (was den count invalidieren würde), damit ist nur noch ein Zugriff über die Funktionen möglich oder ein Read- Only Zugriff über die Property...

DISCLAIMER: Der Code ist im Browser runtergetippt. Er enthält vermutlich Tippfehler und -ganz wichtig- KEINERLEI Error- Handling. Solchen Code würde es bei mir produktiv nie geben. Aber als Basis ist er vermutlich brauchbar.
« Letzte Änderung: 27.02.19 - 09:28:06 von Tode »
Gruss
Torsten (Tode)

P.S.: Da mein Nickname immer mal wieder für Verwirrung sorgt: Tode hat NICHTS mit Tod zu tun. So klingt es einfach, wenn ein 2- Jähriger versucht "Torsten" zu sagen... das klingt dann so: "Tooode" (langes O, das r, s und n werden verschluckt, das t wird zum badischen d)

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz