3

私は次のような文字列のリストを持っています

List<string> MyList = new List<string>
{ 
    "A-B", 
    "B-A", 
    "C-D", 
    "C-E", 
    "D-C",
    "D-E",
    "E-C",
    "E-D",
    "F-G",
    "G-F"
};

リストから重複を削除する必要があります。つまり、「AB」と「BA」が存在する場合は、「AB」のみを保持する必要があります (最初のエントリ)

したがって、結果は次のようになります

"A-B"   
"C-D"
"C-E"   
"D-E"
"F-G"

LINQ を使用してこれを行う方法はありますか?

4

6 に答える 6

14

IEqualityComparer を実装します。ウィッチは Equals("AB", "BA") で true を返します。Enumerable.Distinctメソッドを使用します

于 2010-09-21T06:39:31.953 に答える
12

これは、探しているシーケンスを返します。

var result = MyList
    .Select(s => s.Split('-').OrderBy(s1 => s1))
    .Select(a => string.Join("-", a.ToArray()))
    .Distinct();

foreach (var str in result)
{
    Console.WriteLine(str);
}

つまり、文字の各文字列-を 2 つの要素の配列に分割します。各配列を並べ替えて、再び結合します。次に、単純に使用Distinctして一意の値を取得できます。

更新: もう少し考えてみると、Select呼び出しの 1 つを簡単に削除できることに気付きました。

var result = MyList
    .Select(s => string.Join("-", s.Split('-').OrderBy(s1 => s1).ToArray()))
    .Distinct();

免責事項: このソリューションは、元のシーケンスに表示される順序に関係なく、常に値「BA」よりも「AB」を保持します。

于 2010-09-21T06:44:04.677 に答える
4

オーバーロードを使用できますEnumerable.Distinct(IEnumerable<TSource>, IEqualityComparer<TSource>)

あとは実装するだけですIEqualityComparer。開始するための手順は次のとおりです。

class Comparer : IEqualityComparer<String>
{

    public bool Equals(String s1, String s2)
    {
        // will need to test for nullity
        return Reverse(s1).Equals(s2);
    }

    public int GetHashCode(String s)
    {
        // will have to implement this
    }

}

Reverse()実装については、この質問を参照してください

于 2010-09-21T06:40:45.773 に答える
1

次のように IEqualityComparer を実装する必要があります。

public class CharComparer : IEqualityComparer<string>
{
    #region IEqualityComparer<string> Members

    public bool Equals(string x, string y)
    {
        if (x == y)
            return true;

        if (x.Length == 3 && y.Length == 3)
        {
            if (x[2] == y[0] && x[0] == y[2])
                return true;

            if (x[0] == y[2] && x[2] == y[0])
                return true;
        }

        return false;
    }

    public int GetHashCode(string obj)
    {
        // return 0 to force the Equals to fire (otherwise it won't...!)
        return 0;
    }

    #endregion
}

サンプル プログラム:

class Program
{
    static void Main(string[] args)
    {
        List<string> MyList = new List<string>
        { 
            "A-B", 
            "B-A", 
            "C-D", 
            "C-E", 
            "D-C",
            "D-E",
            "E-C",
            "E-D",
            "F-G",
            "G-F"
        };

        var distinct = MyList.Distinct(new CharComparer());
        foreach (string s in distinct)
            Console.WriteLine(s);

        Console.ReadLine();
    }
}

結果:

「AB」   
"CD"
「CE」   
「デ」
「FG」
于 2010-09-21T07:07:09.060 に答える
1

非常に基本的ですが、より適切に記述できます (ただし、機能しているだけです):

class Comparer : IEqualityComparer<string>
  {
      public bool Equals(string x, string y)
      {
          return (x[0] == y[0] && x[2] == y[2]) || (x[0] == y[2] && x[2] == y[0]);
      }

      public int GetHashCode(string obj)
      {
          return 0;
      }
  }

var MyList = new List<String>
{ 
    "A-B", 
    "B-A", 
    "C-D", 
    "C-E", 
    "D-C",
    "D-E",
    "E-C",
    "E-D",
    "F-G",
    "G-F"
}
.Distinct(new Comparer());

foreach (var s in MyList)
{
    Console.WriteLine(s);
}
于 2010-09-21T06:47:25.710 に答える
-2
int checkID = 0;
while (checkID < MyList.Count)
{
 string szCheckItem = MyList[checkID];
 string []Pairs = szCheckItem.Split("-".ToCharArray());
 string szInvertItem = Pairs[1] + "-" + Pairs[0];
 int i=checkID+1;
 while (i < MyList.Count)
 {
  if((MyList[i] == szCheckItem) || (MyList[i] == szInvertItem))
  {
   MyList.RemoveAt(i);
   continue;
  }
  i++;
 }

 checkID++;
}
于 2010-09-21T06:48:00.400 に答える