Sprache: C#
Diese Erweiterungsmethode vergleicht zwei auflistungen auf Gleichheit. Dabei werden jedoch nicht die Listeninstanzen sondern die Elemente in den Listen verglichen. Auf wunsch wird die Reihenfolge der Elemente ignoriert.
[b]Benötigte Namespaces[/b]
System
System.Collections.Generic
System.Linq
[b]Hinweis[/b]
Die LINQ Methode SequenceEqual erziehlt ein ähnliches Ergebnis. Jedoch erlaubt die Methode keine Angabe, ob die Anordnung der Elemente beachtet werden soll.
[b]Testanwendung[/b]
[code]string[] a1 = { "a", "b", "c", "d", "e" };
string[] a2 = { "a", "b", "c", "d", "e" };
string[] a3 = { "a", "b", "c", "e", "d" };
string[] a4 = { "a", "b", "c", "d" };
string[] a5 = { "a", "a", "a", "b" ,"c"};
string[] a6 = { "a", "a", "b", "b" };
string[] a7 = { "a", "a", "a", "b" };
bool flag = true;//Bitte ändern um den 3. Parameter zu testen
Console.WriteLine(a1.AreItemsEqual(a2, (x, y) => x == y, flag));//immer true
Console.WriteLine(a1.AreItemsEqual(a3, (x, y) => x == y, flag));//true wenn flag = true
Console.WriteLine(a1.AreItemsEqual(a4, (x, y) => x == y, flag));
Console.WriteLine(a1.AreItemsEqual(a5, (x, y) => x == y, flag));
Console.WriteLine(a1.AreItemsEqual(a6, (x, y) => x == y, flag));
Console.WriteLine(a1.AreItemsEqual(a7, (x, y) => x == y, flag));
Console.WriteLine();
Console.WriteLine(a2.AreItemsEqual(a1, (x, y) => x == y, flag));//immer true
Console.WriteLine(a2.AreItemsEqual(a3, (x, y) => x == y, flag));//true wenn flag = true
Console.WriteLine(a2.AreItemsEqual(a4, (x, y) => x == y, flag));
Console.WriteLine(a2.AreItemsEqual(a5, (x, y) => x == y, flag));
Console.WriteLine(a2.AreItemsEqual(a6, (x, y) => x == y, flag));
Console.WriteLine(a2.AreItemsEqual(a7, (x, y) => x == y, flag));
Console.WriteLine();
Console.WriteLine(a3.AreItemsEqual(a1, (x, y) => x == y, flag));//true wenn flag = true
Console.WriteLine(a3.AreItemsEqual(a2, (x, y) => x == y, flag));//true wenn flag = true
Console.WriteLine(a3.AreItemsEqual(a4, (x, y) => x == y, flag));
Console.WriteLine(a3.AreItemsEqual(a5, (x, y) => x == y, flag));
Console.WriteLine(a3.AreItemsEqual(a6, (x, y) => x == y, flag));
Console.WriteLine(a3.AreItemsEqual(a7, (x, y) => x == y, flag));
Console.WriteLine();
Console.WriteLine(a4.AreItemsEqual(a1, (x, y) => x == y, flag));
Console.WriteLine(a4.AreItemsEqual(a2, (x, y) => x == y, flag));
Console.WriteLine(a4.AreItemsEqual(a3, (x, y) => x == y, flag));
Console.WriteLine(a4.AreItemsEqual(a5, (x, y) => x == y, flag));
Console.WriteLine(a4.AreItemsEqual(a6, (x, y) => x == y, flag));
Console.WriteLine(a4.AreItemsEqual(a7, (x, y) => x == y, flag));
Console.WriteLine();
Console.WriteLine(a5.AreItemsEqual(a1, (x, y) => x == y, flag));
Console.WriteLine(a5.AreItemsEqual(a2, (x, y) => x == y, flag));
Console.WriteLine(a5.AreItemsEqual(a3, (x, y) => x == y, flag));
Console.WriteLine(a5.AreItemsEqual(a4, (x, y) => x == y, flag));
Console.WriteLine(a5.AreItemsEqual(a6, (x, y) => x == y, flag));
Console.WriteLine(a5.AreItemsEqual(a7, (x, y) => x == y, flag));
Console.WriteLine();
Console.WriteLine(a6.AreItemsEqual(a1, (x, y) => x == y, flag));
Console.WriteLine(a6.AreItemsEqual(a2, (x, y) => x == y, flag));
Console.WriteLine(a6.AreItemsEqual(a3, (x, y) => x == y, flag));
Console.WriteLine(a6.AreItemsEqual(a4, (x, y) => x == y, flag));
Console.WriteLine(a6.AreItemsEqual(a5, (x, y) => x == y, flag));
Console.WriteLine(a6.AreItemsEqual(a7, (x, y) => x == y, flag));
Console.WriteLine();
Console.WriteLine(a7.AreItemsEqual(a1, (x, y) => x == y, flag));
Console.WriteLine(a7.AreItemsEqual(a2, (x, y) => x == y, flag));
Console.WriteLine(a7.AreItemsEqual(a3, (x, y) => x == y, flag));
Console.WriteLine(a7.AreItemsEqual(a4, (x, y) => x == y, flag));
Console.WriteLine(a7.AreItemsEqual(a5, (x, y) => x == y, flag));
Console.WriteLine(a7.AreItemsEqual(a6, (x, y) => x == y, flag));
Console.ReadKey();[/code]
/// <summary>
/// Überprüft ob die Elemente zweier Listen identisch sind.
/// </summary>
/// <typeparam name="T">Der Typ von dem die Elemente der Liste sind.</typeparam>
/// <param name="source">Die erste Liste.</param>
/// <param name="other">Die zweite Liste.</param>
/// <param name="equal">Eine Funktion zum überprüfen auf Gleichheit.</param>
/// <param name="ignoreOrder"><c>True</c>, wenn die Reihenfolge der Elemente ignoriert werden soll; andernfalls <c>false</c>.</param>
/// <returns><c>true</c>, wenn <paramref name="source"/> und <paramref name="other"/> in den Elementen übereinstimmen; andernfalls <c>false</c>.</returns>
public static bool AreItemsEqual<T>(this IEnumerable<T> source, IEnumerable<T> other, Func<T, T, bool> equal, bool ignoreOrder)
{
if (source == null) throw new ArgumentNullException("source");
if (other == null) throw new ArgumentNullException("other");
if (equal == null) throw new ArgumentNullException("equal");
using (var enu1 = source.GetEnumerator())
{
using (var enu2 = other.GetEnumerator())
{
bool b1 = true, b2 = true;
if (ignoreOrder)
{
foreach (var dist in source.Distinct())
if (source.Count(x => equal(x, dist)) != other.Count(x => equal(x, dist)))
return false;
while ((b1 = enu1.MoveNext()) & (b2 = enu2.MoveNext())) { }
}
else
while ((b1 = enu1.MoveNext()) & (b2 = enu2.MoveNext()))
{
if (!equal(enu1.Current, enu2.Current))
return false;
}
if (b1 != b2)
return false;//one at end, the other not
else
return true;
}
}
}
/// <summary>
/// Überprüft ob die Elemente zweier Listen identisch sind.
/// </summary>
/// <typeparam name="T">Der Typ von dem die Elemente der Liste sind.</typeparam>
/// <param name="source">Die erste Liste.</param>
/// <param name="other">Die zweite Liste.</param>
/// <param name="equal">Eine Funktion zum überprüfen auf Gleichheit.</param>
/// <param name="ignoreOrder"><c>True</c>, wenn die Reihenfolge der Elemente ignoriert werden soll; andernfalls <c>false</c>.</param>
/// <returns><c>true</c>, wenn <paramref name="source"/> und <paramref name="other"/> in den Elementen übereinstimmen; andernfalls <c>false</c>.</returns>
public static bool AreItemsEqual<T>(this IEnumerable<T> source, IEnumerable<T> other, Func<T, T, bool> equal, bool ignoreOrder)
{
if (source == null) throw new ArgumentNullException("source");
if (other == null) throw new ArgumentNullException("other");
if (equal == null) throw new ArgumentNullException("equal");
using (var enu1 = source.GetEnumerator())
{
using (var enu2 = other.GetEnumerator())
{
bool b1 = true, b2 = true;
if (ignoreOrder)
{
foreach (var dist in source.Distinct())
if (source.Count(x => equal(x, dist)) != other.Count(x => equal(x, dist)))
return false;
while ((b1 = enu1.MoveNext()) & (b2 = enu2.MoveNext())) { }
}
else
while ((b1 = enu1.MoveNext()) & (b2 = enu2.MoveNext()))
{
if (!equal(enu1.Current, enu2.Current))
return false;
}
if (b1 != b2)
return false;//one at end, the other not
else
return true;
}
}
}
Alte URL:
/snippet/items-zweier-listen-vergleichen/3846
Wenn du folgendes machst:
[code]
string[] a6 = { „a“, „a“, „b“, „b“ };
string[] a7 = { „a“, „a“, „a“, „b“ };
Console.WriteLine(a6.AreItemsEqual(a7, (x, y) => x == y, true));
[/code]
… wird [b]True[/b] ausgegeben.
Das sollte meiner Ansicht nach [b]False[/b] ergeben.
Wenn du bei [b]ignoreOrder == true[/b] mit [b]Contains[/b] das Vorhandensein eines Wertes überprüfst, ist die Anzahl der gefundenen gleichen Werte irrelevant.
Ich denke aber, die Anzahl der gleichen Werte muss übereinstimmen.
Wenn du bei [b]ignoreOrder == true[/b] die Listen [b]source[/b] und [b]other[/b] sortieren würdest und dann den Vergleich wie bei [b]ignoreOrder == false[/b] machen würdest, müsste es funktionieren.[/b] machen kann.
Ich bin mir aber nicht sicher, ob und wie man das bei [b]IEnumerable
@Pirmin
Du hast recht, so eine Anordnung von Arrayelementen kam in meinem Verwendungszweck nicht vor, darum habe ich es nicht darauf getestet.
Deine Idee mit dem Sortieren der Liste würde zwar funktionieren, aber dafür bräuchte ich noch eine Funktion die die generischen Elemente vergleicht. Das wollte ich vermeiden.
Also habe ich die einzigartigen Elemente aus [b]source[/b] heraus gesucht und die Anzahl dieser Elemente in [b]source[/b] und [b]other[/b] cmit einander verglichen. Sollten alle gleich sein, gehe ich nochmal beide Enumeratoren durch um die Anzahl zu überprüfen. Das geht sollte etwas schneller gehen, als zweimal Count aufzurufen.
Ich habe das Snippet und die Testanwendung entsprechend angepasst.
[b]Danke nochmal für diesen Hinweis![/b]