2

私はこれを持っています:

List<string> list = new List<string>();
list.Add("a-b-c>d");
list.Add("b>c");
list.Add("f>e");
list.Add("f>e-h");
list.Add("a-d>c-b");

重複を削除したい。この場合、重複は「abc>d」と「ad>cb」です。どちらも同じ文字を持っていますが、順序が異なります。私は試してみました:

list.Distinct().ToList();

しかし、うまくいきませんでした!

4

3 に答える 3

10

あなたが望むように見えます:

var distinct = list
    .Select((str, idx) => new { Str = str, Idx = idx })
    .GroupBy(pair => new HashSet<char>(pair.Str), HashSet<char>.CreateSetComparer())
    .Select(grp => grp.OrderBy(p => p.Idx).First())
    .ToList();

これにより、最初の要素が保持され、同じ文字を含むシーケンス内の後続の文字列が削除されます。

Aggregate使用して、既に見た文字セットを追跡することもできます。

var distinct = list
    .Aggregate(new Dictionary<HashSet<char>, string>(HashSet<char>.CreateSetComparer()), (dict, str) =>
    {
        var set = new HashSet<char>(str);
        if (!dict.ContainsKey(set))
            dict.Add(set, str);
        return dict;
    })
    .Values
    .ToList();
于 2013-03-21T20:56:17.557 に答える
5

IEqualityComparer2 つの文字列が「等しい」と見なされるタイミングをシステムが理解できるようにするカスタムを定義する必要があります。例えば:

List<string> list = new List<string>();
list.Add("a-b-c>d");
list.Add("b>c-d-f");
list.Add("c-d-f>e");
list.Add("a-d>c-b");
var distinctItems = list.Distinct(new KeyFuncEqualityComparer<string>(
    s => new String(s.AsEnumerable().OrderBy(c => c).ToArray())));

結果:

a-b-c>d 
b>c-d-f 
c-d-f>e 

... この一般的な IEqualityComparer 実装を使用します。

public class KeyFuncEqualityComparer<T> :IEqualityComparer<T>
{
    private readonly Func<T, object> _getKey;

    public KeyFuncEqualityComparer(Func<T, object> getKey)
    {
        _getKey = getKey;
    }

    public bool Equals(T x, T y)
    {
        return _getKey(x).Equals(_getKey(y));
    }

    public int GetHashCode(T obj)
    {
        return _getKey(obj).GetHashCode();
    }
}
于 2013-03-21T20:56:01.340 に答える