Есть ли способ, которым я могу перебирать назад (в обратном порядке) через SortedDictionary в С#?
Или есть способ определить SortedDictionary в порядке убывания для начала?
Есть ли способ, которым я могу перебирать назад (в обратном порядке) через SortedDictionary в С#?
Или есть способ определить SortedDictionary в порядке убывания для начала?
Сам SortedDictionary не поддерживает обратную итерацию, но у вас есть несколько возможностей для достижения того же эффекта.
Используйте .Reverse
-Method (Linq). (Это должно будет предварительно вычислить весь вывод словаря, но это самое простое решение)
var Rand = new Random();
var Dict = new SortedDictionary<int, string>();
for (int i = 1; i <= 10; ++i) {
var newItem = Rand.Next(1, 100);
Dict.Add(newItem, (newItem * newItem).ToString());
}
foreach (var x in Dict.Reverse()) {
Console.WriteLine("{0} -> {1}", x.Key, x.Value);
}
Сделайте сортировку слова в порядке убывания.
class DescendingComparer<T> : IComparer<T> where T : IComparable<T> {
public int Compare(T x, T y) {
return y.CompareTo(x);
}
}
// ...
var Dict = new SortedDictionary<int, string>(new DescendingComparer<int>());
Вместо этого используйте SortedList<TKey, TValue>
. Производительность не так хороша, как словарь (O (n) вместо O (logn)), но у вас есть произвольный доступ к элементам, например, в массивах. Когда вы используете общий IDictionary-Interface, вам не придется изменять остальную часть вашего кода.
Изменить:: Итерация на SortedLists
Вы просто получаете доступ к элементам по индексу!
var Rand = new Random();
var Dict = new SortedList<int, string>();
for (int i = 1; i <= 10; ++i) {
var newItem = Rand.Next(1, 100);
Dict.Add(newItem, (newItem * newItem).ToString());
}
// Reverse for loop (forr + tab)
for (int i = Dict.Count - 1; i >= 0; --i) {
Console.WriteLine("{0} -> {1}", Dict.Keys[i], Dict.Values[i]);
}
Самый простой способ определить SortedDictionary в обратном порядке для начала - предоставить ему IComparer<TKey>
, который сортируется в обратном порядке до нормального.
Вот код из MiscUtil, который может облегчить вам:
using System.Collections.Generic;
namespace MiscUtil.Collections
{
/// <summary>
/// Implementation of IComparer{T} based on another one;
/// this simply reverses the original comparison.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class ReverseComparer<T> : IComparer<T>
{
readonly IComparer<T> originalComparer;
/// <summary>
/// Returns the original comparer; this can be useful
/// to avoid multiple reversals.
/// </summary>
public IComparer<T> OriginalComparer
{
get { return originalComparer; }
}
/// <summary>
/// Creates a new reversing comparer.
/// </summary>
/// <param name="original">The original comparer to
/// use for comparisons.</param>
public ReverseComparer(IComparer<T> original)
{
if (original == null)
{
throw new ArgumentNullException("original");
}
this.originalComparer = original;
}
/// <summary>
/// Returns the result of comparing the specified
/// values using the original
/// comparer, but reversing the order of comparison.
/// </summary>
public int Compare(T x, T y)
{
return originalComparer.Compare(y, x);
}
}
}
Затем вы использовали:
var dict = new SortedDictionary<string, int>
(new ReverseComparer<string>(StringComparer.InvariantCulture));
(или какой бы тип вы не использовали).
Если вы хотите только итерации в одном направлении, это будет более эффективным, чем последующее изменение порядка.
Существует также очень простой подход, если вы имеете дело с числовыми значениями в качестве ключа, который должен просто отрицать их при создании словаря.
Если вы используете .NET 3.5, вы можете использовать метод расширения OrderByDescending:
var dictionary = new SortedDictionary<int, string>();
dictionary.Add(1, "One");
dictionary.Add(3, "Three");
dictionary.Add(2, "Two");
dictionary.Add(4, "Four");
var q = dictionary.OrderByDescending(kvp => kvp.Key);
foreach (var item in q)
{
Console.WriteLine(item.Key + " , " + item.Value);
}