2016-05-17 6 views
4

ファイル(CSVやExcelなど)からデータを読み込み、ファイルの各行が一意であることを確認する必要があります。オブジェクトの配列の一意性を確認する

各行はobject[]で表されます。これは、現在のアーキテクチャのために変更することはできません。この配列内の各オブジェクトは異なるタイプ(decimalstringintなど)です。

ファイル次のようになります

foo 1  5 // Not unique 
bar 1  5 
bar 2  5 
foo 1  5 // Not unique 

ファイルが200.000+行と列4-100を持っている可能性があります。

私が今持っているコードは次のようになります。

IList<object[]> rows = new List<object[]>(); 

using (var reader = _deliveryObjectReaderFactory.CreateReader(deliveryObject)) 
{ 
    // Read the row. 
    while (reader.Read()) 
    { 
     // Get the values from the file. 
     var values = reader.GetValues(); 

     // Check uniqueness for row 
     foreach (var row in rows) 
     { 
      bool rowsAreDifferent = false; 

      // Check uniqueness for column. 
      for (int i = 0; i < row.Length; i++) 
      { 
       var earlierValue = row[i]; 
       var newValue = values[i]; 
       if (earlierValue.ToString() != newValue.ToString()) 
       { 
        rowsAreDifferent = true; 
        break; 
       } 
      } 
      if(!rowsAreDifferent) 
       throw new Exception("Rows are not unique"); 
     } 
     rows.Add(values); 
    } 
} 

だから、私の質問は、これはより効率的に行うことができますか?ハッシュを使用するなど、代わりにハッシュの一意性をチェックしますか?

+0

あなたは、2つのオブジェクトが同じハッシュを持ち、まだ不等である可能性があることを認識していますか?言い換えれば、あなたのハッシュが正しく行われた場合、ファイルは重複ハッシュを持つことができますが、依然としてユニークな行を持ちます。 – phoog

+1

HashSet をカスタム同値比較ツールで使用するとどうなりますか? – Jehof

+0

@phoog、はい私はそれをよく知っています。解はまずハッシュをチェックし、ハッシュが等しい場合は他の値もチェックする必要があります。しかし、常にすべての値をチェックするのではなく、ハッシュを最初にチェックするほうが効率的かもしれません。 – smoksnes

答えて

4

あなたはそのようなカスタムIEqualityComparer<object[]>HashSet<object[]>使用することができます:a==b一部の作品ならば、私は完全にはわからない

public class MyComparer : IEqualityComparer<object[]> 
{ 
    public bool Equals(object[] x, object[] y) 
    { 
     if (ReferenceEquals(x, y)) return true; 
     if (ReferenceEquals(x, null) || ReferenceEquals(y, null) || x.Length != y.Length) return false; 
     return x.Zip(y, (a, b) => a == b).All(c => c); 
    } 
    public int GetHashCode(object[] obj) 
    { 
     unchecked 
     { 
      // this returns 0 if obj is null 
      // otherwise it combines the hashes of all elements 
      // like hash = (hash * 397)^nextHash 
      // if an array element is null its hash is assumed as 0 
      // (this is the ReSharper suggestion for GetHashCode implementations) 
      return obj?.Aggregate(0, (hash, o) => (hash * 397)^(o?.GetHashCode() ?? 0)) ?? 0; 
     } 
    } 
} 

HashSet<object[]> rows = new HashSet<object[]>(new MyComparer()); 

while (reader.Read()) 
{ 
    // Get the values from the file. 
    var values = reader.GetValues();  
    if (!rows.Add(values)) 
     throw new Exception("Rows are not unique"); 
} 

そしてMyComparerがそのように実装することができることをすべてのタイプに対して。

+0

ああ、ちょうど@Jehofが私が書いている間にこれを示唆していたことを知っていたので、おそらくすでにそれをする方法を知っていたでしょう... –

+0

はい、今。しかし、派手なC#6機能はありません。 ;) – smoksnes

+0

最後の返信文は私には全く怖かったです。私はおそらく、良い量のコーヒーと15分の時間を把握する必要があるでしょう、なぜそれが何をしますか。 '? '演算子についてコメントし、なぜ391を掛けるのですか? – Marco

関連する問題