Могу ли я использовать Linq для создания компаратора для отсортированного словаря С#

Есть ли способ создать SortedDictionary с помощью Linq? Это позволит избежать неудобств (и раздувания кода) создания класса компаратора.

Например, создайте словарь, отсортированный по обратной стороне строкового ключа:

//NOT VALID SYNTAX
SortedDictionary<string, int> sortDict = new SortedDictionary(kvp => new String(kvp.Key.Reverse().ToArray());

//VALID SYNTAX
SortedDictionary<string, int> sortDict = new SortedDictionary<string, int>(new ReverseStringComparer);

private class ReverseStringComparer: IComparer<String>
{
    public int Compare(string x, string y)
    {
        string s1 = new string(x.Reverse().ToArray());
        string s2 = new string(y.Reverse().ToArray());
        return s1.CompareTo(s2);
    }
}

person Paul Richards    schedule 04.02.2014    source источник
comment
Почему бы вам не использовать ReverseComparer<T> Джона Скита, который более эффективен?   -  person Tim Schmelter    schedule 04.02.2014
comment
Предлагаемый класс ReverseStringComparer переворачивает каждую строку, а затем сравнивает их. Версия Джона Скита только инвертирует порядок сортировки.   -  person Dirk    schedule 04.02.2014
comment
@TimSchmelter Я думаю, что OP переворачивает строки перед сортировкой, а не сортирует в обратном порядке.   -  person Matthew Watson    schedule 04.02.2014
comment
@MatthewWatson: да, но Reverse().ToArray()) избыточен, так как он мог просто поменять местами x и y, не так ли?   -  person Tim Schmelter    schedule 04.02.2014
comment
Я бы не стал использовать LINQ только ради использования LINQ. Это всего лишь инструмент, используйте его, когда это уместно. На мой взгляд, эти несколько строк вряд ли можно назвать раздуванием кода.   -  person Dirk    schedule 04.02.2014
comment
LINQ не создает компараторов. Но методы LINQ (например, OrderBy) могут использовать компараторы.   -  person Selman Genç    schedule 04.02.2014
comment
Мой код фактически сравнивает ToString() некоторых сложных объектов. Обращение строки - это просто пример, который я придумал для целей этого вопроса (возможно, мне следовало сделать это яснее и использовать лучший пример).   -  person Paul Richards    schedule 04.02.2014


Ответы (1)


Вы можете определить общий класс компаратора, который применяет функцию извлечения к элементам, которые вы хотите сравнить:

public class KeyComparer<TItem, TKey> : Comparer<TItem>
{
    private readonly Func<TItem, TKey> extract;
    private readonly IComparer<TKey> comparer;

    public KeyComparer(Func<TItem, TKey> extract)
        : this(extract, Comparer<TKey>.Default)
    { }

    public KeyComparer(Func<TItem, TKey> extract, IComparer<TKey> comparer)
    {
        this.extract = extract;
        this.comparer = comparer;
    }

    public override int Compare(TItem x, TItem y)
    {
        // need to handle nulls
        TKey xKey = extract(x);
        TKey yKey = extract(y);
        return comparer.Compare(xKey, yKey);
    }
}

Я обычно использую этот класс для извлечения свойств; однако вы можете определить любую функцию, такую ​​как обращение строки:

SortedDictionary<string, int> sortDict = new SortedDictionary<string, int>(
    new KeyComparer<string, string>(s => new string(s.Reverse().ToArray())));

Обновление: я подробно описал этот компаратор в своем сообщении в блоге. .

person Douglas    schedule 04.02.2014