Диапазоны с Linq и словарями - PullRequest
1 голос
/ 01 сентября 2009

Я создал тип диапазона:

public class Range<T> where T : IComparable<T>
{
    public Range(T min, T max) : this(min, max, false) { }
    public Range(T min, T max, bool upperbound)
    {
    }
    public bool Upperbound { get; private set; }
    public T Min { get; private set; }
    public T Max { get; private set; }
    public bool Between(T Value)
    {
        return Upperbound ? (Min.CompareTo(Value) < 0) && (Value.CompareTo(Max) <= 0) : (Min.CompareTo(Value) <= 0) && (Value.CompareTo(Max) < 0);
    }
}

Я хочу использовать это как ключ в словаре, чтобы позволить мне выполнять поиск по диапазону. И да, диапазоны могут перекрываться или могут быть пробелы, что является частью дизайна. Это выглядит просто, но я хочу, чтобы поиск был еще немного проще! Я хочу сравнить диапазон со значением типа T, поэтому я могу использовать: myRange == 10 вместо myRange.Between (10).

Как? :-) (Не хочу ломать голову над этим. Я, вероятно, найду ответ, но, может быть, я заново изобретаю колесо или что-то в этом роде.)


Что я хочу сделать с этим словарем? Ну, в общем, я буду использовать сам диапазон в качестве ключа. Диапазон будет использоваться не только для словаря. Я имею дело с большим количеством данных, которые имеют минимальный / максимальный диапазон, и мне нужно сгруппировать их, основываясь на одинаковых минимальных / максимальных значениях. Значение в словаре представляет собой список этих продуктов, которые имеют одинаковый диапазон. И используя диапазон, я могу быстро найти правильный список, куда мне нужно добавить товар. (Или создайте новую запись, если список не найден.)

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

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

Могу ли я использовать список вместо? Возможно, но тогда у меня не было бы четкой группировки моих данных, основанной на самом диапазоне. Список списков тогда? Возможно, но потом я снова рассматриваю Словарь. : -)


Примеры диапазона: у меня есть несколько элементов с диапазоном от 0 до 100. Другие элементы с диапазоном от 0 до 1, от 1 до 2, от 2 до 3 и т. д. Больше элементов с диапазоном от 0 до 4, От 4 до 6, от 6 до 8 и т. Д. У меня даже есть предметы с диапазонами от 0 до 0,5, от 0,5 до 1, от 1 до 1,5 и т. Д. Итак, сначала я сгруппирую все элементы по их диапазонам, поэтому все элементы с диапазоном 1 до 2 будут вместе в одном списке, а все элементы с диапазоном от 0 до 100 будут в другом списке. Я рассчитал, что буду иметь дело примерно с 50 различными диапазонами, которые могут перекрывать друг друга. Однако у меня есть более 25000 предметов, которые нужно сгруппировать следующим образом.

Далее я получаю значение из другого источника. Например значение 1.12, которое мне нужно найти. Так что на этот раз я использую Linq для поиска по словарю, чтобы найти все списки элементов, где 1.12 будет в диапазоне ключей. Таким образом, я бы нашел диапазон от 1 до 2, от 1 до 1,5 и даже от 0 до 100. За этими диапазонами были бы списки элементов, которые мне нужно обработать для этого значения. И тогда я могу перейти к следующему значению, примерно для 4000 различных значений. И желательно, чтобы все закончилось за 5 секунд.

1 Ответ

6 голосов
/ 01 сентября 2009

Использование ключа в словаре - это вопрос переопределения GetHashCode и Equals. По сути, вы должны создать хеш на основе минимальных и максимальных значений и Upperbound. Обычно вы вызываете GetHashCode для каждого компонента и объединяете их, например ::10000

public override int GetHashCode()
{
    int result = 17;
    result = result * 31 + Min.GetHashCode();
    result = result * 31 + Max.GetHashCode();
    result = result * 31 + Upperbound ? 1 : 0;
}

Вам также понадобится тест на равенство.

Я не уверен, что вы подразумеваете под "разрешить мне выполнять поиск по диапазону". Не могли бы вы привести пример кода, показывающий, как вы хотите использовать эту способность? Я не совсем уверен, что это будет соответствовать обычному словарному подходу ...

Я предлагаю вам не перегружать оператор ==, чтобы вы могли провести с ним тест на сдерживание. Диапазон не равен значению в диапазоне, поэтому использование кода не будет очень интуитивно понятным.

(я бы лично переименовал Between в Contains.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...