SORU
8 EYLÜL 2008, PAZARTESİ


Ne olursa olsun, eşitlik için iki koleksiyon onlara öğelerin sırasını karşılaştırılması

İki koleksiyonları karşılaştırmak istiyorum (C#), ama bu verimli bir şekilde uygulamak için en iyi yolu emin değilim.

Enumerable.SequenceEqual, hakkında başka bir iş parçacığı okudum ama aradığım şey tam olarak o değil.

Benim durumumda, iki koleksiyon eğer onlar aynı maddeler olursa olsun, sipariş) içeriyorsa, her ikisi de eşit olacaktır.

Örnek:

collection1 = {1, 2, 3, 4};
collection2 = {2, 4, 1, 3};

collection1 == collection2; // true

Ne ben genellikle yapmak için bir döngü şeklinde her maddenin bir koleksiyon ve eğer varsa, diğer koleksiyon, daha sonra döngü içinde her maddenin diğer toplama ve eğer varsa ilk koleksiyonu. (Uzunlukları karşılaştırarak başlıyorum).

if (collection1.Count != collection2.Count)
    return false; // the collections are not equal

foreach (Item item in collection1)
{
    if (!collection2.Contains(item))
        return false; // the collections are not equal
}

foreach (Item item in collection2)
{
    if (!collection1.Contains(item))
        return false; // the collections are not equal
}

return true; // the collections are equal

Ancak, bu tamamen doğru değildir, ve muhtemelen karşılaştırın eşitlik için iki koleksiyon yapmak için en etkili yol değil.

Yanlış olacağını düşünemiyorum bir örnektir:

collection1 = {1, 2, 3, 3, 4}
collection2 = {1, 2, 2, 3, 4}

Benim uygulama ile eşit olurdu. Sadece her madde bulundu ve sayıları her iki koleksiyon eşit olduğundan emin olun sayısını saymak gerekir?

< / ^ hr .

Örnekler C çeşit# (hadi pseudo-C#), ama ne olursa olsun dil isteyen, fark etmez cevabını ver.

Not:Ben kullanılan tamsayı örnekler için basitlik, ama olmak istiyorum kullanabilir başvuru türü nesneler de (onlar davranır doğru olarak anahtarları, çünkü tek referans nesnesidir göre değil, içerik).

CEVAP
24 EYLÜL 2010, Cuma


Microsoft zaten bu test çerçevesi kaplı olduğu ortaya çıkıyor: CollectionAssert.AreEquivalent

Açıklamalar

İki koleksiyon eğer eşdeğerdir aynı elementleri aynı var miktar, ancak herhangi bir sırada. Elemanları eğer kendi değerlerinin eşit olması durumunda,eşit eğer aynı nesne ifade ederse.

Reflektör kullanarak, AreEquivalent arkasında kodu değiştirilmiş() karşılık gelen eşitlik karşılaştırıcısı oluşturmak için. Dikkate boşluk alır, IEqualityComparer uygular ve bazı verim ve kenar durumda denetler beri varolan cevaplar daha fazla bilgi. ARTI, bu kadarMicrosoft:)

public class MultiSetComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> first, IEnumerable<T> second)
    {
        if (first == null) 
            return second == null;

        if (second == null)
            return false;

        if (ReferenceEquals(first, second)) 
            return true;

        var firstCollection = first as ICollection<T>;
        var secondCollection = second as ICollection<T>;
        if (firstCollection != null && secondCollection != null)
        {
            if (firstCollection.Count != secondCollection.Count)
                return false;

            if (firstCollection.Count == 0) 
                return true;
        }

        return !HaveMismatchedElement(first, second);
    }

    private static bool HaveMismatchedElement(IEnumerable<T> first, IEnumerable<T> second)
    {
        int firstNullCount;
        int secondNullCount;

        var firstElementCounts = GetElementCounts(first, out firstNullCount);
        var secondElementCounts = GetElementCounts(second, out secondNullCount);

        if (firstNullCount != secondNullCount || firstElementCounts.Count != secondElementCounts.Count)
            return true;

        foreach (var kvp in firstElementCounts)
        {
            var firstElementCount = kvp.Value;
            int secondElementCount;
            secondElementCounts.TryGetValue(kvp.Key, out secondElementCount);

            if (firstElementCount != secondElementCount)
                return true;
        }

        return false;
    }

    private static Dictionary<T, int> GetElementCounts(IEnumerable<T> enumerable, out int nullCount)
    {
        var dictionary = new Dictionary<T, int>();
        nullCount = 0;

        foreach (T element in enumerable)
        {
            if (element == null)
            {
                nullCount  ;
            }
            else
            {
                int num;
                dictionary.TryGetValue(element, out num);
                num  ;
                dictionary[element] = num;
            }
        }

        return dictionary;
    }

    public int GetHashCode(IEnumerable<T> enumerable)
    {
        int hash = 17;

        foreach (T val in enumerable.OrderBy(x => x))
            hash = hash * 23   ((val == null) ? 42 : val.GetHashCode());

        return hash;
    }
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • CZTUTORIALS

    CZTUTORIALS

    28 Ocak 2011
  • infodirt

    infodirt

    11 Mart 2009
  • Wild Academy

    Wild Academy

    8 Aralık 2009