SortedList не сортируется по ключу - VB.NET

Мне нужна пара ключ-значение, которую я хочу отсортировать, поэтому я решил использовать SortedList вместо HashTable.

Я добавляю данные в указанном ниже порядке в свой SortedList, в котором они мне нужны.

     Key          | Value
     --------------------------------
 1   "700-800"    | List(Of Object)
 2   "900-1000"   | List(Of Object)
 3   "1100-1200"  | List(Of Object)
 4   "1700-1800"  | List(Of Object)
 5   "1900-2000"  | List(Of Object)

Ключ представляет собой строку, а значение — список объектов. Ключ представляет временной интервал, который был объединен из двух целочисленных значений и разделен знаком "-". «700» в виде строки изначально было целым числом 0700.

e.g.

Dim key As String = slotTimeStart.ToString() & "-" & slotTimeEnd.ToString()

Но как только эти пары ключ-значение добавляются в SortedList, они появляются в порядке

 3   "1100-1200"  | List(Of Object)
 4   "1700-1800"  | List(Of Object)
 5   "1900-2000"  | List(Of Object)
 1   "700-800"    | List(Of Object)
 2   "900-1000"   | List(Of Object)

К сожалению, я получаю слоты времени в виде двух целых значений, которые нельзя изменить.

Есть ли способ принудительно отсортировать SortedList? или это проблема из-за того, как я храню свой ключ? Есть ли лучший способ сохранить его?


person w4ymo    schedule 24.03.2009    source источник


Ответы (4)


Создайте SortedList(Of String, List(Of Object)), но передайте IComparer(Of String) на конструктор, где реализация будет сравнивать ключи в соответствии с желаемым порядком.

Вам придется реализовать это самостоятельно, но это не должно быть слишком сложно — просто разделите строку на «-», проанализируйте обе стороны с помощью Int32.Parse и отреагируйте соответствующим образом. Возможно, вам даже не нужно беспокоиться о части после «-», если ваши диапазоны клавиш не перекрываются.

РЕДАКТИРОВАТЬ: Вот демо. Он только распечатывает ключи, но этого достаточно, чтобы показать, что они отсортированы так, как вы хотите.

using System;
using System.Collections.Generic;

public class Test
{
    static void Main(string[] args)
    {
        var list = new SortedList<string, int>(new RangeComparer());
        list.Add("900-1000", 10);
        list.Add("1100-1200", 20);
        list.Add("700-800", 30);
        list.Add("1700-18000", 40);
        list.Add("1900-2000", 50);

        foreach (var entry in list)
        {
            Console.WriteLine(entry.Key);
        }
    }
}

public class RangeComparer : IComparer<string>
{
    private static int ParseStartOfRange(string range)
    {
        int hyphenIndex = range.IndexOf('-');
        // Normally do some error checking in case hyphenIndex==-1
        string firstPart = range.Substring(0, hyphenIndex);
        return int.Parse(firstPart);
    }

    public int Compare(string first, string second)
    {
        // In real code you would probably add nullity checks
        int firstStart = ParseStartOfRange(first);
        int secondStart = ParseStartOfRange(second);
        return firstStart.CompareTo(secondStart);
    }
}
person Jon Skeet    schedule 24.03.2009
comment
Спасибо, Джон. Вы имеете в виду, что когда я добавляю ключ, как указано в сообщении выше, я делаю следующее при добавлении его в отсортированный список SortedList.Add(key.ToString(New Comparer(реализация здесь), List(Of Object)) Поскольку я никогда не использовал IComparer, не могли бы вы привести пример? - person w4ymo; 25.03.2009
comment
Нет — вы предоставляете IComparer(T) при создании SortedList. Перейдите по ссылке, которую я дал для конструктора слов :) Я не могу привести пример прямо сейчас, так как мне нужно приготовить ужин, а мой VB ужасен. Сможете ли вы следовать примеру C#? - person Jon Skeet; 25.03.2009
comment
Привет, Джон, не знал, что есть ссылки. Я все еще новичок в макете переполнения стека :) да, это было бы здорово. Я программист на С# по профессии, только в компании, которой нужен vb.net - person w4ymo; 25.03.2009
comment
Спасибо Джон, попробую это завтра, теперь я должен спать - person w4ymo; 25.03.2009

Похоже, вы сортируете его по алфавиту, а не по номерам. Вам нужно будет сделать свой ключ числовым, чтобы получить порядок сортировки, который вы ищете.

person Cᴏʀʏ    schedule 24.03.2009
comment
Нет, SortedList позволяет довольно легко настраивать порядок сортировки. - person Jon Skeet; 25.03.2009

Времена длиной менее 4 цифр должны иметь префикс нуля («0»), чтобы сделать их той же длины, что и времена с 4 цифрами. Таким образом, стандартный компаратор будет сравнивать char 1 строки 1, которая теперь будет 0, с char 1 строки 2, которая будет 1, и строка 1 выйдет первой.

person Community    schedule 22.06.2009

могут ли ключи быть десятичными и выглядеть как

7.08
9.1
11.12
17.18
19.20

и конвертировать и форматировать в строку по мере необходимости.

    Dim sl As New SortedList(Of Decimal, Object)
    'sample data
    For x As Integer = 7 To 20 Step 2
        sl.Add(CDec(x + ((x + 1) / 100)), New Object)
    Next

    Dim aKey As Decimal
    Dim slotStart As DateTime = #1:00:00 PM#
    Dim slotEnd As DateTime = #2:00:00 PM#

    aKey = CDec(slotStart.Hour + (slotEnd.Hour / 100))
    sl.Item(aKey) = New Object
person dbasnett    schedule 24.03.2009