Эквивалент сортированного словаря, который позволяет дублировать ключи
Мне нужна структура данных, которая может сортировать объекты с помощью поплавковых ключей, с которыми они связаны. Проблема в том, что ключи представляют собой стоимость, поэтому часто дублируются, меня это не волнует, потому что, если у двух есть такая же стоимость, я просто возьму первый, так как это не имеет никакого значения, проблема в том, что компилятор жалуется.
Существует ли структура данных, которая ведет себя одинаково, но позволяет дублировать ключи?
EDIT - мне все еще нужны дубликаты, потому что, если кто-то оказывается тупиком, я хватаю следующий (это узлы в поиске *)
чтобы просто быть понятным, ему нужно разрешить дублирование ключей, отсортированных по порядку.
Ответы
Ответ 1
Вы пишете:
эквивалент словаря, который позволяет дублировать ключи
Мне нужна структура данных, которая может сортировать объекты по поплавковым ключам, с которыми они связаны, младший сначала.
Словарь не сохраняет элементы, отсортированные по ключам, поэтому структура, которую вы ищете, на самом деле не эквивалентна Dictionary
. То, что вы хотите, похоже на SortedList
или SortedDictionary
, за исключением того, что оно должно допускать дублирование ключей.
В .NET такого класса нет. Однако у вас есть несколько вариантов:
- Используйте
SortedDictionary<double, List<TValue>>
, если вы хотите сохранить все значения, связанные с ключом, даже если вам обычно нужен только первый. При вставке ключа в первый раз создайте новый список и добавьте значение в список. При вставке ключа, который уже существует, выберите список и добавьте его в список.
- Ваше редактирование означает, что этот подход не применяется к вашей ситуации.
Используйте SortedDictionary<double, TValue>
и проверяйте дубликаты перед вставкой. Только первое значение для каждой клавиши будет сохранено, поэтому, в отличие от вышеприведенного подхода, вы не можете получить доступ ко второму значению с помощью этого метода.
- Найдите библиотеку сторонних коллекций, в которой есть класс, который делает то, что вам нужно.
Похожие
Ответ 2
Я часто сталкивался с этой проблемой, и я всегда использую публичную лицензию (то есть бесплатную) Power Collections от Wintellect (http://powercollections.codeplex.com). У них есть OrderedMultiDictionary, который именно вы ищете. Он позволяет дублировать ключи и позволяет выполнять итерацию всех дубликатов ключевых записей.
Ответ 3
Вы ищете Поиск.
Подобно другим предлагаемым уже основанным на словах решениям, он хранит IEnumerable под каждым ключом для обработки дубликатов.
var registry = Items.ToLookup(item=>item.Price);
foreach(var item in registry[desiredPrice])
{
//Here you handle items that all have Price == desiredPrice
}
Ответ 4
Вы можете создать свой собственный класс, который происходит от SortedSet
:
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
Ответ 5
Вы все равно можете использовать словарь. Вам просто нужно изменить тип значений для коллекций, а не отдельных элементов:
Dictionary<float, List<T>>
Словарь - это определение не позволяет дублировать ключи.
Ответ 6
То, о чем вы говорите, это сумка. Разница между сумкой и набором заключается в том, что наборы уникальны, а сумки позволяют дублировать. {a, b, c} - множество; {a, b, c, a} - мешок.
Возьмите копию C5 Collections Library. Вам нужны классы HashBag<T>
или TreeBag<T>
. Разница в том, что основное хранилище данных в одном - это хеш и красно-черное дерево в другом. Внешне они ведут себя одинаково. Либо должен дать вам то, что вы хотите.
Ответ 7
То, что вы ищете, называется heap
или priority queue
. Я уверен, что если вы Google, вы найдете его для С#
Ответ 8
Вы должны иметь возможность использовать SortedDictionary с пользовательской реализацией IComparer, чтобы избежать столкновений. Например:
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);
}
}
Ответ 9
Вы можете сделать это, переопределив CompareTo fucntion. Когда вы добавляете элемент в SortedDictionary, он использует CompareTo(), если результат равен 0, вызывает исключение, но вы можете изменить поведение компаратора реализации вашего ключевого класса, чтобы вернуться только выше или ниже (1 или -1)
public int CompareTo(int key)
{
if (this.key.CompareTo(key) < 1)
return 1;
else
return -1;
}