При использовании ключей Comparer для сравнения по их значениям из словаря SortedDictionary всегда выдает исключение - PullRequest
1 голос
/ 13 апреля 2020

Я хочу достичь кучи с SortedDictionary, который сравнивает значения вместо ключей. Мои элементы находятся в словаре, и я добавил их один за другим в SortedDictionary. Это всегда исключение во 2-й раз из метода «Добавить» в l oop. Msgstr "Запись с таким же ключом уже существует". Поскольку я получил элементы из словаря, я знаю, что ключи не могут быть одинаковыми. Что я должен сделать, чтобы такой SortedDictionary работал? Большое спасибо!

dic = new Dictionary<int, int>();
var sort = new SortedDictionary<int, int>(Comparer<int>.Create((x, y) => dic[x].CompareTo(dic[y])));
foreach (var pair in dic)
{
    sort.Add(pair.Key, pair.Value);
}

1 Ответ

0 голосов
/ 13 апреля 2020

Вы можете попробовать следующий подход:

var sort = new SortedDictionary<int, int>(
    Comparer<int>.Create(
        (x, y) => 
        {
            int vx = dic[x];
            int vy = dic[y];

            // If values are the same then compare keys.
            if (vx == vy)
                return x.CompareTo(y);

            // Otherwise - compare values.
            return vx.CompareTo(vy);
        }));

Если вы объявите sort, используя этот подход, тогда Keys в sort будет упорядочено по Values. Вот полный пример , который показывает, как работает этот подход.


@ SylvainLIU спросил:

Что меня смущает, в моем первоначальном посте: используя dic [x] .CompareTo (dic [y]) я имел в виду получить возвращаемое значение метода Compare (), но не принимать dic [x] или dic [y] в качестве ключа SortedDictionary. Почему их просят быть уникальными?

Вы были правы, и ваш образец работал так, как вы предполагали. Так почему же было выдано исключение?

SortedDictionary должен содержать уникальные ключи. Указывая Comparer для SortedDictionary, мы указываем, как заказать ключи и как определить, является ли новый ключ уникальным. Если Comparer возвращает 0 для нового ключа, то этот ключ не является уникальным, и будет выдано исключение An entry with the same key already exists.

Если мы используем сравнение dic[x].CompareTo(dic[y]), то для сравнения ключей x и y мы используем их значения dic[x] и dic[y]. Например, пусть у нас есть две пары (Key=1, Value=3) и (Key=2, Value=3). Если для их сравнения мы используем Comparer dic[x].CompareTo(dic[y]), то ключи этих пар не являются уникальными, поскольку они сравниваются по своим значениям: 3.CompareTo(3) = 0. Конечно, значения 1 и 2 - это разные числа, но с точки зрения компаратора dic[x].CompareTo(dic[y]) они одинаковы. Поэтому, если мы используем этот компаратор, мы должны гарантировать, что значения пар должны быть уникальными, чтобы предотвратить повторяющиеся ошибки.

Если мы используем следующий компаратор

int vx = dic[x];
int vy = dic[y];

// If values are the same then compare keys.
if (vx == vy)
    return x.CompareTo(y);

// Otherwise - compare values.
return vx.CompareTo(vy);

, тогда значения dic должны не быть уникальным, поскольку этот компаратор учитывает, что значения в dic могут быть одинаковыми, и для этого случая он использует другую стратегию для упорядочения и проверки уникальности.

...