2016-06-17 12 views
0

私は文字列配列のリストを持っています。文字列配列の最初の要素のみをチェックすることによって、重複や空の文字列を削除したい。 IEqualityComparerを使っていくつかのSOの投稿を見て、重複している文字列全体を比較して、もっとエレガントで効率的に見えると思っています。しかし、IEqualityComparerが私を混乱させるため、文字列配列の最初の要素だけをチェックして不要な要素を削除することに失敗しました。どのようにこれをよりエレガントに達成することができますか?私の現在の非エレガント&非効率的な作業コード:C#重複のみを削除する文字列配列の最初の要素をチェックする

void method(List<string[]> contactAndNumber) 
{ 
    List<string[]> contactAndNumberSanitized = new List<string[]>(); 
    contactAndNumberSanitized.Clear(); 
    bool rem = false; 
    List<int> remList = new List<int>(); 
    for (int i = 0; i < contactAndNumber.Count; i++) 
    { 
     contactAndNumberSanitized.Add(new string[] { contactAndNumber[i][0], contactAndNumber[i][1] }); 
     for (int j = 0; j < contactAndNumberSanitized.Count; j++) 
      if (i != j) 
       if (contactAndNumber[i][0] == contactAndNumberSanitized[j][0]) 
       { 
        rem = true; 
        break; 
       } 
     if (rem || string.IsNullOrEmpty(contactAndNumber[i][0])) 
      remList.Add(i); 
     rem = false; 
    } 
    for (int i = remList.Count - 1; i >= 0; i--) 
     contactAndNumberSanitized.RemoveAt(remList[i]); 
} 

そして、これは私が唯一の文字列の配列の最初の項目にチェックを行うことを実現しようとした非稼働コードです:ことで

sealed class EqualityComparer: IEqualityComparer<string[]> 
{ 
    public bool Equals(string[] x, string[] y) 
    { 
     if (ReferenceEquals(x[0], y[0])) 
      return true; 

     if (x == null || y == null) 
      return false; 

     return x[0].SequenceEqual(y[0]); 
    } 

    public int GetHashCode(string[] obj) 
    { 
     if (obj == null) 
      return 0; 

     int hash = 17; 

     unchecked 
     { 
      foreach (string s in obj) 
       hash = hash*23 + ((s == null) ? 0 : s.GetHashCode()); 
     } 

     return hash; 
    } 
} 

いくつかの方法の下でこれを呼び出す:

var result = list.Distinct(new EqualityComparer()); 

答えて

3

あなたのコードを大幅に簡素化することができます。

var input = new List<string[]> { new[] { "a", "b" }, new[] { "a", "c" }, new[] { "c", "d" }}; 
var result = input.GroupBy(l => l.FirstOrDefault()).Select(g => g.First()); 

これにより、各アレイの最初の要素を使用して一意性を判断する独自の配列が得られます。

ただし、一意性を判断するために配列の最初の要素を使用しているため、空のセットが{ null }と等しいと見なされる場合があります。あなたは空集合をどのように処理するかに応じて、あなたはT >一覧<で作業しているので、あなたがREMOVEALLメソッドを使用することができ、入力をフィルタリングするためにコードを変更する必要がある、またはGroupBy

+0

:「」sの3のセットの中の「A」)は、その後、あなたは私の元の答えを使用することができます。メイト - トップブリーク! =)空の文字列キーを持つ配列を削除することは、このLINQクエリ内にも実装できますか? –

+1

@BarryGuvenkayaもちろん、グループの前にフィルタを追加します。 GroupBy(... '。)空の配列をすべて削除し、' null'を最初の配列として持つ配列を削除します(および/または空の配列を削除することはできません)またはただ)要素 – Rob

0

を変更します。

編集:元の回答が機能しない可能性があります。以下の改訂。

編集2:あなたは(元を離れることなく)すべての重複を削除したい場合は、実際に、この使用:

var duplicates = data.Where(x => x == null || string.IsNullOrEmpty(x[0]) || data.Where(y => y != null).Count(y => y[0] == x[0]) > 1).ToList(); 
data.RemoveAll(x => duplicates.Contains(x)); 

しかしを、あなたは(重複のセットで最後を残しておきたい場合など、最後のそれは1行のソリューションですので、私は答えとしてこれを受け入れてい

data.RemoveAll(x => x == null || string.IsNullOrEmpty(x[0]) || data.Where(y => y != null).Count(y => y[0] == x[0]) > 1); 
+0

残念ながら、これは私のために働かなかった。とにかくあなたの素早い答えをありがとう。 –

関連する問題