vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#

https://www.vbarchiv.net
Rubrik: Variablen/Strings · Array/ArrayList   |   VB-Versionen: VB200809.02.09
Vergleich von zwei Arrays

Erweiterung zur Prüfung, ob zwei Arrays identisch deklariert sind und ihre Elemente den gleichen Inhalt besitzen.

Autor:   Manfred BohnBewertung:  Views:  16.499 
ohne HomepageSystem:  Win2k, WinXP, Vista, Win7, Win8, Win10kein Beispielprojekt 

Die Überprüfung, ob zwei System.Arrays gleich sind, ist in Visual Basic relativ einfach, falls die Elemente die IComparable-Schnittstelle implementiert haben. Das trifft z.B. auf alle sog. Primitiven Typen zu.

Man überprüft zunächst die Rahmenkonstruktion der Arrays (Nothing, Type, Rank, Bounds). Die Nothing-Prüfung ist erforderlich, weil Array-Variable Referenztypen sind, auch wenn die Elemente aus einem Werttyp bestehen.

Findet man beim Vergleich eine identische Rahmenkonstruktion, überträgt man die Array-Elemente jeweils in ein eindimensionales Object-Array, um die Rank-spezifische Indizierung loszuwerden (per Linq / ToArray-Erweiterung). Der Typ der einzelnen Array-Elemente bleibt dabei erhalten, es ändert sich nur die Array-Variable.

Durch eine einfache Schleife können die korrespondierenden Array-Elemente miteinander verglichen werden (Nothing, Type, Content). Die Nothing- und Type-Checks sind erforderlich, weil Arrays Element-Referenzen auf alle möglichen Strukturen, Objekte und auch auf Nothing enthalten können.

Die Erweiterungen 'IsEqual' heften sich an Arrays, deren Array-Variablen-Deklaration signalisiert, dass die Comparable-Schnittstelle implementiert ist. Sie erlauben als Parameter nur Arrays, die die gleiche Zahl von Dimensionen aufweisen (1-3).

Die Erweiterung 'Equality' heftet sich an alles, was nach einem System.Array aussieht. Als Parameter wird ebenfalls jedes System.Array zur Entwicklungszeit akzeptiert. Falls die Array-Elemente die IComparable-Schnittstelle nicht implementiert haben, wird eine Ausnahme ausgelöst.

Einige Beispiele:

Module modArrayEqual_Exempl
  Public Sub IsArrayEqual_Exempl()
    Dim i1(), i2() As Short
 
    If i1.IsEqual(i2) Then Stop
    ' ---> Stop erreicht, weil beide Nothing sind
 
    Dim i3(0) As Short
    If Not i1.IsEqual(i3) Then Stop
    ' ---> Stop erreicht, weil 'i3' nicht nothing ist
 
    Dim i4(0) As Integer
    If Not i3.Equality(i4) Then Stop
    ' ---> Stop erreicht, weil unterschiedliche Array-Typen vorliegen
 
    Dim i5(0, 0) As Short
    If Not i3.Equality(i5) Then Stop
    ' ---> Stop erreicht, weil unterschiedliche Dimensionen vorliegen
 
    Dim i6(0, 1) As Short
    If Not i5.IsEqual(i6) Then Stop
    ' ---> Stop erreicht, weil unterschiedliche Grenzen vorliegen
 
    Dim i7(0, 1) As Short
    i7(0, 0) = 1
    If Not i6.IsEqual(i7) Then Stop
    ' ---> Stop erreicht, weil unterschiedliche Arrayinhalte vorliegen
 
    Dim t1 As String = "Test1", t2 As String = "TEST1"
    If Not t1.ToCharArray.IsEqual(t2.ToCharArray) Then Stop
    ' ---> Stop erreicht, weil case-sensitiver Vergleich vorgenommen wird
 
    Dim c1(0) As Object, c2(0) As Object
    c1(0) = 1% : c2(0) = 1.0#
    If Not c1.Equality(c2) Then Stop
    ' ---> Stop erreicht, weil Elementtyp Integer <> Double ist
 
    Dim oa1(10), oa2(10) As Object
    oa1(0) = CShort(0)
    oa1(1) = 1 : oa1(2) = 2.0! : oa1(3) = 3.0#
    oa1(4) = "x"c
    oa1(5) = CByte(5) : oa1(6) = CULng(6)
    oa1(7) = 1.0#
    For i As Integer = 0 To 10 : oa2(i) = oa1(i) : Next i
    oa2(7) = CDbl(oa1(7)) + (1000.0# * Double.Epsilon)
    If oa1.Equality(oa2) Then Stop
    ' ---> Stop wird erreicht, weil beide Arrays als gleich gelten
    ' Der Unterschied ist im Datentyp nicht darstellbar
 
    Dim p1(5) As cPersonalDaten
    Dim p2(5) As cPersonalDaten
    p1(0) = New cPersonalDaten("Maier", "Hans", "Schlosser")
    p1(1) = New cPersonalDaten("Müller", "Georg", "Pfoertner")
    p1(2) = New cPersonalDaten("Schneider", "Eduard", "Maschinist")
    p1(4) = New cPersonalDaten("Gerber", "Harald", "Buchhalter")
 
    For i As Integer = 0 To p1.Length - 1
      If Not p1(i) Is Nothing Then
        With p1(i)
          '  echte Kopien der Instanzen durch Konstruktor erstellen
          p2(i) = New cPersonalDaten(._Name, ._Vorname, ._Position)
        End With
      End If
    Next i
 
    If p1.IsEqual(p2) Then Stop
    ' ---> Stop wird erreicht, weil alle Elemente identisch sind,
    ' auch die Nothing-Elemente !!!
  End Sub
  ''' <summary>Demoklasse, implementiert IComparable für
  ''' Vergleich von Instanzen (nicht zum Sortieren geeignet!!)
  ''' </summary>
  Private Class cPersonalDaten
    Implements IComparable
 
    ' öffentliche Membervariablen
    Public _Vorname As String
    Public _Name As String
    Public _Position As String
 
    ''' <summary>Demoklasse, implementiert IComparable für
    ''' Vergleich von Instanzen (nicht zum Sortieren geeignet!!)
    ''' </summary>
    Public Sub New(ByVal name As String, _
      ByVal vorname As String, _
      ByVal position As String)
 
      _Name = name
      _Vorname = vorname
      _Position = position
    End Sub
 
    Public Function CompareTo(ByVal obj As Object) As Integer _
      Implements System.IComparable.CompareTo
      If Me.Equals(obj) Then Return 0
      Dim v As cPersonalDaten = CType(obj, cPersonalDaten)
      With v
        If _Vorname <> ._Vorname Then Return -1
        If _Name <> ._Name Then Return -1
        If _Position <> ._Position Then Return -1
      End With
      Return 0
    End Function
  End Class
End Module
Option Strict On
Option Explicit On
Option Infer Off
 
Imports System
Imports System.Math
Imports System.Linq.Enumerable
 
Module modIsArrayEqual
  ''' <summary>
  ''' Prüfung der Gleichheit von zwei System.Arrays
  ''' Vergleich: Rank, Bounds, Type, Content (per IComparable)
  ''' </summary>
  ''' <param name="arr1">1. zu vergleichendes Array</param>
  ''' <param name="arr2">2. zu vergleichendes Array</param>
  ''' <returns>true falls identisch, sonst false</returns>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function IsEqual(Of T As IComparable) _
    (ByVal arr1 As T(), ByVal arr2 As T()) As Boolean
    Return Equality(arr1, arr2)
  End Function
  ''' <summary>
  ''' Prüfung der Gleichheit von zwei System.Arrays
  ''' Vergleich: Rank, Bounds, Type, Content (per IComparable)
  ''' </summary>
  ''' <param name="arr1">1. zu vergleichendes Array</param>
 ''' <param name="arr2">2. zu vergleichendes Array</param>
  ''' <returns>true falls identisch, sonst false</returns>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function IsEqual(Of T As IComparable) _
    (ByVal arr1 As T(,), ByVal arr2 As T(,)) As Boolean
    Return Equality(arr1, arr2)
  End Function
  ''' <summary>Prüfung der Gleichheit von zwei System.Arrays
  ''' Vergleich: Rank, Bounds, Type, Content (per IComparable)
  ''' </summary>
  ''' <param name="arr1">1. zu vergleichendes Array</param>
  ''' <param name="arr2">2. zu vergleichendes Array</param>
  ''' <returns>true falls identisch, sonst false</returns>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function IsEqual(Of T As IComparable) _
    (ByVal arr1 As T(,,), ByVal arr2 As T(,,)) As Boolean
    Return Equality(arr1, arr2)
  End Function
  ''' <summary>Prüfung der Gleichheit von zwei System.Arrays
  ''' Vergleich: Rank, Bounds, Type, Content (per IComparable)
  ''' </summary>
  ''' <param name="arr1">1. zu vergleichendes Array</param>
  ''' <param name="arr2">2. zu vergleichendes Array</param>
  ''' <returns>true falls identisch, sonst false</returns>
  <System.Runtime.CompilerServices.Extension()> _
  Public Function Equality _
    (ByVal arr1 As System.Array, ByVal arr2 As System.Array) As Boolean
 
    Dim iarr1(), iarr2() As Object
    Dim typ1, typ2 As System.Type
    Dim el1, el2 As IComparable
 
    ' Nothing = Nothing
    If arr1 Is Nothing And arr2 Is Nothing Then Return True
 
    ' Ein einzelner Nothing-Parameter führt immer zu 'false'
    If arr1 Is Nothing Or arr2 Is Nothing Then Return False
 
    ' Identisches Objekt?
    If arr1.Equals(arr2) Then Return True
 
    ' Datentyp und Rank der Arrays vergleichen?
    If Not arr1.GetType.Equals(arr2.GetType) Then Return False
 
    ' Index-Obergrenzen vergleichen
    For i As Integer = 0 To arr1.Rank - 1
      If arr1.GetUpperBound(i) <> arr2.GetUpperBound(i) Then Return False
    Next i
 
    ' Array-Elemente per Linq in 
    ' eindimensionale Arrays eintragen
    iarr1 = (From x In arr1).ToArray
    iarr2 = (From x In arr2).ToArray
 
    For i As Integer = 0 To iarr1.Length - 1
      ' Vergleich der Array-Elemente (IComparable)
      If iarr1(i) Is Nothing Or iarr2(i) Is Nothing Then
        ' Vergleich von Nothing-Elementen
        If iarr1(i) Is Nothing And Not iarr2(i) Is Nothing Then Return False
        If Not iarr1(i) Is Nothing And iarr2(i) Is Nothing Then Return False
      Else
        ' Typ der korrespondierenden Array-Elemente
        typ1 = iarr1(i).GetType : typ2 = iarr2(i).GetType
 
        ' Gleicher Typ?
        If Not typ1.Equals(typ2) Then Return False
 
        ' Gleicher Inhalt?
        el1 = CType(iarr1(i), IComparable)
        el2 = CType(iarr2(i), IComparable)
        If el1.CompareTo(el2) <> 0 Then Return False
      End If
    Next i
    Return True
  End Function
End Module



Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
 
Copyright ©2000-2019 vb@rchiv Dieter OtterAlle Rechte vorbehalten.


Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.