我需要一种数据结构,可以按与它们相关联的浮点键进行排序,最低的排在前面。问题在于这些键表示成本,因此通常会出现重复值,但我并不在意这一点,因为如果两个对象具有相同的成本,我只需取第一个,因为这没有任何影响,问题是编译器会抱怨。
是否有一种数据结构行为相同但允许重复键呢?
编辑 - 我仍然需要这些重复项,因为如果其中一个变成死胡同,我会选择下一个(它们是a *搜索中的节点)
所以,清楚了吗,它需要允许按顺序排序的重复键。
我需要一种数据结构,可以按与它们相关联的浮点键进行排序,最低的排在前面。问题在于这些键表示成本,因此通常会出现重复值,但我并不在意这一点,因为如果两个对象具有相同的成本,我只需取第一个,因为这没有任何影响,问题是编译器会抱怨。
是否有一种数据结构行为相同但允许重复键呢?
编辑 - 我仍然需要这些重复项,因为如果其中一个变成死胡同,我会选择下一个(它们是a *搜索中的节点)
所以,清楚了吗,它需要允许按顺序排序的重复键。
你写道:
相当于允许重复键的字典
我需要一种数据结构,可以按它们关联的浮点键进行排序对象,最低的优先。
字典不会按键排序项,因此你想要的结构实际上根本不等同于 Dictionary
。你想要的是类似于 SortedList
或 SortedDictionary
的东西,只是它应该允许重复键。
.NET 中没有这样的类。但是你有几个选择:
SortedDictionary<double,List<TValue>>
。 插入首次键时,请创建新列表并将值添加到列表中。插入已经存在的键时,请获取列表并将值附加到列表中。SortedDictionary<double, TValue>
并在插入之前检查重复项。每个键仅存储第一个值,因此与上述方法不同,使用此方法无法访问第二个值。相关的
SortedDictionary
或者SortedList
。已经更新了回答。 - Mark ByersSortedSet
派生的自定义类:public class SortedTupleBag<TKey, TValue> : SortedSet<Tuple<TKey, TValue>>
where TKey : IComparable
{
private class TupleComparer : Comparer<Tuple<TKey, TValue>>
{
public override int Compare(Tuple<TKey, TValue> x, Tuple<TKey, TValue> y)
{
if (x == null || y == null) return 0;
// If the keys are the same we don't care about the order.
// Return 1 so that duplicates are not ignored.
return x.Item1.Equals(y.Item1)
? 1
: Comparer<TKey>.Default.Compare(x.Item1, y.Item1);
}
}
public SortedTupleBag() : base(new TupleComparer()) { }
public void Add(TKey key, TValue value)
{
Add(new Tuple<TKey, TValue>(key, value));
}
}
在控制台应用程序中的使用方法:
private static void Main(string[] args)
{
var tuples = new SortedTupleBag<decimal, string>
{
{2.94M, "Item A"},
{9.23M, "Item B"},
{2.94M, "Item C"},
{1.83M, "Item D"}
};
foreach (var tuple in tuples)
{
Console.WriteLine("{0} {1}", tuple.Item1, tuple.Item2);
}
Console.ReadKey();
}
生成这个结果:
1.83 Item D
2.94 Item A
2.94 Item C
9.23 Item B
我遇到过很多次这个问题,我总是使用来自Wintellect的公共许可证(即免费)Power Collections(http://powercollections.codeplex.com)。他们有一个OrderedMultiDictionary,正是你需要的。它允许重复的键,并且允许您迭代所有重复的键条目。
var registry = Items.ToLookup(item=>item.Price);
foreach(var item in registry[desiredPrice])
{
//Here you handle items that all have Price == desiredPrice
}
ToLookup
。我撤销了我的负评。 - Marlon您可以通过覆盖CompareTo函数来实现。当您向SortedDictionary添加元素时,它会使用CompareTo(),如果结果为0,则会抛出异常,但是您可以更改键类实现的比较器行为,仅返回大于或小于(1或-1)。
public int CompareTo(int key)
{
if (this.key.CompareTo(key) < 1)
return 1;
else
return -1;
}
您仍然可以使用字典。您只需要将值的类型更改为集合而不是单个项:
Dictionary<float, List<T>>
字典的定义不允许有重复的键。
HashBag<T>
或TreeBag<T>
类。它们之间的区别在于一个的底层数据存储是哈希,另一个是红黑树。从外部看,它们的行为相同。任何一个都应该能给你想要的东西。private class NonCollidingFloatComparer : IComparer<float>
{
public int Compare(float left, float right)
{
return (right > left) ? -1 : 1; // no zeroes
}
}
// silly method for the sake of demonstration
public void sortNodes(List<Node> nodesToSort)
{
SortedDictionary<float, Node> nodesByWeight = new SortedDictionary<float, Node>(new NonCollidingFloatComparer());
foreach (Node n in nodesToSort)
{
nodesByWeight.Add(n.FloatKey, n);
}
foreach (Node n in nodesByWeight.Values)
{
Console.WriteLine(n.FloatKey + " : " + n.UniqueID);
}
}
IEnumerable<T>
或者你喜欢的任何集合类型? - ceyko