62

要素を 1 つずつステップ実行する以外に、2 つの文字列リストを比較して等価性を確認するにはどうすればよいですか (.NET 3.0 の場合):

これは失敗します:

// Expected result.
List<string> expected = new List<string>();
expected.Add( "a" );
expected.Add( "b" );
expected.Add( "c" );

// Actual result
actual = new List<string>();
actual.Add( "a" );
actual.Add( "b" );
actual.Add( "c" );

// Verdict
Assert.IsTrue( actual == expected );
4

9 に答える 9

79

以下を試してください

var equal = expected.SequenceEqual(actual);

テスト版

Assert.IsTrue( actual.SequenceEqual(expected) );

SequenceEqual 拡張メソッドは、コレクションの要素が等しいかどうかを比較します。

http://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspxを参照してください。

于 2009-10-10T03:20:03.047 に答える
42

多くのテスト フレームワークは CollectionAssert クラスを提供します。

CollectionAssert.AreEqual(expected, actual);

例: MS テスト

于 2009-10-10T03:32:15.113 に答える
13

必要な関数はいつでも自分で書くことができます。

public static bool ListEquals<T>(IList<T> list1, IList<T> list2) {
    if (list1.Count != list2.Count)
        return false;
    for (int i = 0; i < list1.Count; i++)
        if (!list1[i].Equals(list2[i]))
            return false;
    return true;
}

そしてそれを使用します:

// Expected result.
List<string> expected = new List<string>();
expected.Add( "a" );
expected.Add( "b" );
expected.Add( "c" );

// Actual result
actual = new List<string>();
actual.Add( "a" );
actual.Add( "b" );
actual.Add( "c" );

// Verdict
Assert.IsTrue( ListEquals(actual, expected) );
于 2009-10-10T03:51:59.347 に答える
10

元のコードが機能しなかった理由を実際に誰も教えてくれなかったことに気付きました。これは==、一般に、演算子がオーバーロードされていない限り、演算子は等価性を参照する(つまり、2 つのインスタンスがメモリ内の同じオブジェクトを指しているかどうか) ためです。 演算子を定義しないため、基本参照 equals 実装が使用されます。List<T>==

他の投稿者が示したように、「コレクションの等価性」をテストするには、通常、要素をステップ実行する必要があります。もちろん、ユーザーDreamWalkerによって提案された最適化を使用する必要があります。この最適化では、最初にコレクションのカウントをテストしてからステップスルーします。

于 2009-10-10T04:04:01.547 に答える
9

順序が重要な場合:

bool equal = a.SequenceEquals(b);

順序が重要でない場合:

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b);
于 2016-01-21T11:24:46.853 に答える
1

Linq を使用して、コードを拡張メソッドとして記述します。

public static bool EqualsOtherList<T>(this List<T> thisList, List<T> theOtherList)
{
  if (thisList == null || theOtherList == null || 
      thisList.Count != theOtherList.Count) return false;
  return !thisList.Where((t, i) => !t.Equals(theOtherList[i])).Any();
}
于 2015-10-25T02:56:18.877 に答える
1

次のような拡張メソッドを作成できます。

public static class ListExtensions
    {
        public static bool IsEqual<T>(this IList<T> list,IList<T> target, IComparer<T> comparer) where T:IComparable<T>
        {
            if (list.Count != target.Count)
            {
                return false;
            }
            int index = 0;
            while (index < list.Count && 
                   comparer.Compare(list[index],target[index]) == 0)
            {
                index++;
            }
            if (index != list.Count)
            {
                return false;
            }
            return true;
        }
    }

そして、次のように呼び出します。

List<int> intList = new List<int> { 1, 234, 2, 324, 324, 2 };
List<int> targetList = new List<int> { 1, 234, 2, 324, 324 };
bool isEqual = intList.IsEqual(targetList, Comparer<int>.Default);

編集:OPは.NET 3.0を使用しているため、代わりに静的メソッドを使用するようにコードを更新しました

public static bool IsEqual<T>(IList<T> sourceList, IList<T> targetList, IComparer<T> comparer) where T : IComparable<T>
        {
            if (sourceList.Count != targetList.Count)
            {
                return false;
            }
            int index = 0;
            while (index < sourceList.Count &&
                   comparer.Compare(sourceList[index], targetList[index]) == 0)
            {
                index++;
            }
            if (index != sourceList.Count)
            {
                return false;
            }
            return true;
        }

クライアント:

        bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default);
于 2009-10-10T04:12:27.980 に答える
0

コレクションを反復処理しますが、私が作成したこの拡張メソッドは、2 つのリストの順序が同じである必要はなく、Equals メソッドがオーバーライドされている限り、複雑な型でも機能します。

次の 2 つのリストは true を返します。

List<string> list1 = new List<string>
{
    { "bob" },
    { "sally" },
    { "john" }
};

List<string> list2 = new List<string>
{
    { "sally" },
    { "john" },
    { "bob" }
};

方法:

public static bool IsEqualTo<T>(this IList<T> list1, IList<T> list2)
{
    if (list1.Count != list2.Count)
    {
        return false;
    }

    List<T> list3 = new List<T>();

    foreach (var item in list2)
    {
        list3.Add(item);
    }

    foreach (var item in list1)
    {
        int index = -1;
        for (int x = 0; x < list3.Count; x++)
        {
            if (list3[x].Equals(item))
            {
                index = x;
            }
        }

        if (index > -1)
        {
            list3.RemoveAt(index);
        }
        else
        {
            return false;
        }
    }

    return !list3.Any();
}
于 2015-09-28T14:25:56.393 に答える
0

通常の方法ではなく、カスタム型の IEquatable を実装せずに使用される可能性があります

JsonConvert.SerializeObject( myList1) == JsonConvert.SerializeObject( myList2)

ただし、一般的には、コメントに記載されているように SequenceEqual を使用できますhttps://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=netframework-4.8

また、カスタム型の IEquatable インターフェイスを実装することを忘れないでください (文字列型やその他の構造には必要ありません)。

于 2019-05-30T14:21:08.157 に答える