2013-02-21 17 views

cevap

1

İhtiyacınız olan eksiksiz ve çalışan bir uygulamadır.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ListsAndArrays 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<int[]> propIDs = new List<int[]>(); 
      propIDs.Add(new[] { 1, 2 }); 
      propIDs.Add(new[] { 4, 5 }); 
      propIDs.Add(new[] { 1, 5 }); 
      propIDs.Add(new[] { 1, 2 }); 
      propIDs.Add(new[] { 1, 5 }); 

      var distinct = propIDs.Distinct(new DistinctIntegerArrayComparer()); 

      foreach (var item in distinct) 
      { 
       Console.WriteLine("{0}|{1}", item[0], item[1]); 
      } 

      if (Debugger.IsAttached) 
      { 
       Console.ReadLine(); 
      } 
     } 

     private class DistinctIntegerArrayComparer : IEqualityComparer<int[]> 
     { 
      public bool Equals(int[] x, int[] y) 
      { 
       if (x.Length != y.Length) { return false; } 
       else if (x.Length != 2 || y.Length != 2) { return false; } 

       return x[0] == y[0] && x[1] == y[1]; 
      } 

      public int GetHashCode(int[] obj) 
      { 
       return -1; 
      } 
     } 

    } 
} 
+2

Bu işe yaramakla birlikte, sabit (burada '-1') karma kodu döndürmek, _worst_ mümkündür (hala doğru) uygulamasıdır. –

+0

@JeppeStigNielsen, Ne söylediğini anlayabiliyorum ve geri bildirim için teşekkürler! Diziler aynı olduğunda aslında aynı olacak bir karma kodu oluşturmak muhtemelen daha iyi bir yaklaşımdır - özellikle çok büyük bir dizi dizi ile *** ilgileniyorsanız ***. Bununla birlikte, diğer yayınlardan da görebileceğiniz gibi, bir karma kodu oluşturmak doğru değildir ve açıkça görüşe göre farklılık gösterir. Küçük bir dizi diziyle burada herhangi bir gerçek performans vuruşu yok. –

3

bir eşitlik karşılaştırıcısı alır Enumerable.Distinct aşırı yüklenmesini kullanabilirsiniz almak gerekir. senin int dizileri her iki öğe uzunsa da bir olmadan Distinct kullanmanızı sağlayacak olan yerine Tuple s kullanabilirsiniz,

class IntArrayComparer : IEqualityComparer<int[]> 
{ 
    public bool Equals(int[] left, int[] right) 
    { 
     if (left.Length != right.Length) return false; 

     return left.SequenceEquals(right); 
    } 

    public int GetHashCode(int[] arr) 
    { 
     unchecked 
     { 
      int hc = 1; 

      foreach (int val in arr) hc = hc * 397^val.GetHashCode(); 
     } 
    } 
} 

:

class IntPairArrayComparer : IEqualityComparer<int[]> 
{ 
    public bool Equals(int[] left, int[] right) 
    { 
     if (left.Length != 2) throw new ArgumentOutOfRangeException("left"); 
     if (right.Length != 2) throw new ArgumentOutOfRangeException("right"); 

     return left[0] == right[0] && left[1] == right[1]; 
    } 

    public int GetHashCode(int[] arr) 
    { 
     unchecked 
     { 
      return (arr[0].GetHashCode() * 397)^arr[1].GetHashCode(); 
     } 
    } 
} 

IEnumerable<int[]> distinctPairs = propIDs.Distinct(new IntPairArrayComparer()); 

Eğer çiftleri daha büyük koleksiyonları istiyorsanız özel eşitlik karşılaştırıcısı:

IEnumerable<Tuple<int, int>> propIDs = [] { Tuple.Create(1,2), … }; 
IEnumerable<Tuple<int, int>> distinctPairs = propIDs.Distinct(); 
+0

Dizilerin farklı uzunlukları varsa ne olur? – daryal

+0

Eminim ki bu bile derlenmeyecek. Ve çalışmak için GetHashCode() yöntemini almanın bir hilesi var. Statik olarak bir '-1 'döndürmeniz gerekir, böylece' Equals' yöntemini bile çalıştıracaktır. –

+0

@MichaelPerrenoud: 'GetHashCode 'uygulamasını ekledi. –

-1

HashSet, bir dizi yinelenen öğeleri içeren bir koleksiyon:

var propIDs = HashSet<Tuple<int,int>> 
1

Bu kod, uzunluk dizileri için geçerlidir.

class MyEqualityComparer : IEqualityComparer<int[]> 
    { 
     public bool Equals(int[] item1, int[] item2) 
     { 
      if (item1 == null && item2 == null) 
       return true; 
      if ((item1 != null && item2 == null) || 
        (item1 == null && item2 != null)) 
       return false; 
      return item1.SequenceEqual(item2); 
     } 

     public int GetHashCode(int[] item) 
     { 
      if(item == null) 
      { 
       return int.MinValue; 
      } 
      int hc = item.Length; 
      for (int i = 0; i < item.Length; ++i) 
      { 
       hc = unchecked(hc * 314159 + item[i]); 
      } 
      return hc; 
     } 
    } 

ve farklı kod:

var result = propIDs.Distinct(new MyEqualityComparer()); 
1

sen kullanamazsınız varsayarsak zaten yerine basitçe tüm elementlerin istenerek diziler için eşitlik tanımlayan kendi IEqualityComparer<T> oluşturabilir eşitliği sağlayan Tuple<T1, T2>

class ArrayEqualityComparer<T> : IEqualityComparer<T[]> { 

    public Boolean Equals(T[] x, T[] y) { 
    if (x.Length != y.Length) 
     return false; 
    return x.Zip(y, (xx, yy) => Equals(xx, yy)).All(equal => equal); 
    } 

    public Int32 GetHashCode(T[] obj) { 
    return obj.Aggregate(0, (hash, value) => 31*hash + value.GetHashCode()); 
    } 

} 

Sonra kolayca ayrı değerler elde edebilirsiniz: eşit sıralı olan

var distinctPropIDs = propIDs.Distinct(new ArrayEqualityComparer<Int32>()); 
0
public return List<Tuple<double, double>> uniquePairs(List<double[]> lst) 
{ 
HashSet<Tuple<double, double>> hash = new HashSet<Tuple<double, double>>(); 
for (int i = 0; i < lst.count; i++) 
{ 
hash.Add(new Tuple<double, double>(lst[i][0], lst[i][1])) 
} 
List<Tuple<double, double>> lstt = hash.Distinct().ToList(); 
} 

For example: 
List<double[]> lst = new List<double[]> {new double[] { 1, 2 }, new double[] { 2, 3 }, new double[] { 3, 4 }, new double[] { 1, 4 }, new double[] { 3, 4 }, new double[] { 2, 1 }}; // this list has 4 unique numbers, 5 unique pairs, the desired output would be the 5 unique pairs (count = 5) 
List<Tuple<double, double>> lstt = uniquePairs(lst); 
Console.WriteLine(lstt.Count().ToString()); 

çıkış 5

İlgili konular