使用 Comparer 通过字典中的值来比较键,SortedDictionary 总是抛出异常
With a Comparer to comparer keys by their values from a dictionary, SortedDictionary always throw exception
我想用 SortedDictionary 实现一个堆,它比较值而不是键。我的元素在字典中,我将它们一一添加到 SortedDictionary 中。它总是在第二次从循环中的 "Add" 方法抛出异常。 "An entry with the same key already exists"。
因为我从字典中得到了元素,所以我知道键不能相同。我应该怎么做才能使这样的 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);
}
您可以尝试下一个方法:
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
,则 sort
中的 Keys
将按 Values
排序。 complete sample 展示了这种方法的工作原理。
@SylvainLIU 问:
What confuse me is, in my original post, by using
dic[x].CompareTo(dic[y]) I meant to get the return value of the
Compare() method, but not to take dic[x] or dic[y] as Key of the
SortedDictionary. Why they're asked to be unique?
你是对的,你的样本如你所想的那样工作。那为什么会抛出异常呢?
SortedDictionary
必须包含唯一键。通过为 SortedDictionary
指定 Comparer
,我们指定了如何对键进行排序以及如何定义新键是否唯一。如果 Comparer
returns 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)
。如果我们使用比较器 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
中的值可以是相同的,对于这种情况,它使用另一种策略来排序和检查唯一性。
我想用 SortedDictionary 实现一个堆,它比较值而不是键。我的元素在字典中,我将它们一一添加到 SortedDictionary 中。它总是在第二次从循环中的 "Add" 方法抛出异常。 "An entry with the same key already exists"。 因为我从字典中得到了元素,所以我知道键不能相同。我应该怎么做才能使这样的 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);
}
您可以尝试下一个方法:
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
,则 sort
中的 Keys
将按 Values
排序。 complete sample 展示了这种方法的工作原理。
@SylvainLIU 问:
What confuse me is, in my original post, by using dic[x].CompareTo(dic[y]) I meant to get the return value of the Compare() method, but not to take dic[x] or dic[y] as Key of the SortedDictionary. Why they're asked to be unique?
你是对的,你的样本如你所想的那样工作。那为什么会抛出异常呢?
SortedDictionary
必须包含唯一键。通过为 SortedDictionary
指定 Comparer
,我们指定了如何对键进行排序以及如何定义新键是否唯一。如果 Comparer
returns 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)
。如果我们使用比较器 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
中的值可以是相同的,对于这种情况,它使用另一种策略来排序和检查唯一性。