kanut писал(а):Например, есть коллекция Dictionary(Of Integer, Integer) с ключами 1, 2, 2.1, 2.1, 5, 7.5, 7.5, 9
kanut писал(а):Нужно выделить из нее все ключи от 2 до 7.9 не используя цикл, перебор всех ключей.
kanut писал(а):Нужно выделить из нее все ключи от 2 до 7.9 не используя цикл, перебор всех ключей
FireFenix писал(а):Если шаг ключей определённый, то ...
FireFenix писал(а):Но от этого будет профит, если ключей больше чем запрашиваемый диапазон, а так обычный перебор быстрее
FireFenix писал(а):Если не изменяет память, можно заюзать SortedList
Qwertiy писал(а):Dictionary не может содержать совпадающих ключей. И числа у тебя не Integer.
kanut писал(а):Странно, если действительно такой стандартной возможности нет.
Qwertiy писал(а):FireFenix писал(а):Но от этого будет профит, если ключей больше чем запрашиваемый диапазон, а так обычный перебор быстрее?
kanut писал(а):Кстати, я не смог найти типа коллекций подобных List
kanut писал(а):Если нет, тогда придется писать функцию выбора самому - деление пополам, сравнение, снова деление, снова сравнение и т.д.
kanut писал(а):Нужно, чтобы коллекция типа "ключ (возможно повторяющиеся числа, тип Double)-значение (возможно повторяющиеся числа, тип массив Double())"
kanut писал(а):быстро возвращала один или несколько своих ключей
kanut писал(а):Количество элементов в коллекции - до 1-10 миллионов и при этом выборка диапазона будет очень частой. Надо делать выборку максимально быстро для VB Net.
FireFenix писал(а):Зачем другие коллекции если есть List? и более того есть SortedList!
FireFenix писал(а):Быстро это как? 100мс? 200мс? O(1)? O(n)?
FireFenix писал(а):Для этого будет эффективнее использовать СУБД (если локально, то типа SQLite)
kanut писал(а):FireFenix писал(а):Зачем другие коллекции если есть List? и более того есть SortedList!
Извиняюсь, я до этого думал, что List это сортированная коллекция, просто в нее можно добавлять одинаковые ключи и они будут идти подряд. Сейчас проверил, а они идут в порядке добавления... Значит коллекций с повторяющимися ключами в Framework нет. Тогда подходит только SortedDictionary(Of Double, List(Of Double)) и при добавлении ключа, который уже был в коллекции, буду запихивать массив (который предполагался сначала) в коллекцию List(). К счастью, количество элементов массива стандартное.
kanut писал(а):FireFenix писал(а):Быстро это как? 100мс? 200мс? O(1)? O(n)?
Намного быстрее перебора подряд, быстрейшим из доступных способов.
kanut писал(а):FireFenix писал(а):Для этого будет эффективнее использовать СУБД (если локально, то типа SQLite)
Лучше, если не найду стандартного средства в Framework, то сделаю функцию сам.
FireFenix писал(а):Это же очевидно, если массив имеет диапазон ключей 0-100, а ты запрашиваешь 90-100, то профит перебора 10*[шаг перебора] ключей против 100.
FireFenix писал(а):Какое-то наркоманство для работы с диапазонами. Для этого будет эффективнее использовать СУБД (если локально, то типа SQLite)
FireFenix писал(а):Быстро это как? 100мс? 200мс? O(1)? O(n)?
kanut писал(а):Тогда подходит только SortedDictionary(Of Double, List(Of Double))
kanut писал(а):Лучше, если не найду стандартного средства в Framework, то сделаю функцию сам.
FireFenix писал(а):SortedList это смесь List + Dictionary.
FireFenix писал(а):Преимущество SortedList над SortedDictionary это наличие Индексов, что позволяет ускорить поиск и не использовать любые виды переборов
FireFenix писал(а):Лучше правильно поставить задачу и найти правильно решение, чего вы не делаете.
kanut писал(а):Периодически будут добавляться новые пары ключ-значение.
kanut писал(а):Те, элементы что уже есть не удаляются, не меняются.
FireFenix писал(а):Проблему одинаковых элементов можно решить добавив Массив на выходе с ключа. SortedList(Of Double, List(Of Double))
FireFenix писал(а):Чисто теоретически:
На одном ядре с частотой 3,3ГГц при отсутствии кеш-промаха и высоким приоритетом задачи получаем ~3млрд операций.
Перебор в цикле это 2х(cmp (x64 - 1, х86 - 3) + jmp) + inc + jmp ~ 10 инструкций.
Того мы получаем что ваши 10 миллионов записей будут обработаны за 1 /( 3млрд/ (10*10млн)) ~ 33,3мс.
FireFenix писал(а):SortedList это смесь List + Dictionary
FireFenix писал(а):Тогда почему вы уверены что перебор подряд очень долгая операция?
Qwertiy писал(а):FireFenix писал(а):Какое-то наркоманство для работы с диапазонами. Для этого будет эффективнее использовать СУБД (если локально, то типа SQLite)
Не говори фигню!
Qwertiy писал(а):FireFenix писал(а):Быстро это как? 100мс? 200мс? O(1)? O(n)?
O(lb n) - очевидно же.
Qwertiy писал(а):FireFenix писал(а):SortedList это смесь List + Dictionary.
Не правда. SortedList - это List. Да он отсортирован, но при вставке минимального элемента всё сдвигается, выполняя O(n) действий.
Qwertiy писал(а):FireFenix писал(а):Преимущество SortedList над SortedDictionary это наличие Индексов, что позволяет ускорить поиск и не использовать любые виды переборов
Да, обращение по индексду для SortedList O(1), поиск O(lb n).
kanut писал(а):Это очевидно. За 33 мс мне нужно уже выбрать уйму диапазонов, а не перебрать 1 раз все элементы.
Кстати, 10 млн. записей это максимум, а начинаться коллекция будет с 1 элемента.
class Program
{
static void Main(string[] args)
{
int maxVal = 104857600; // 104.857.600
Dictionary<int, int> srcDict = new Dictionary<int, int>(maxVal);
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < maxVal; i++) { srcDict.Add(i, i); }
sw.Stop();
Console.WriteLine(String.Format("Fill Dictionary (0 to 104.857.600 items): {0} ms.",
sw.ElapsedMilliseconds));
sw.Reset();
sw.Start();
IEnumerable<KeyValuePair<int, int>> query = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 256789 && item.Key < 1024789)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw.Stop();
Console.WriteLine(String.Format("Query for > 256.789 and < 1.024.789 : {0} ms, Total Items: {1}",
sw.ElapsedMilliseconds, query.Count<KeyValuePair<int,int>>()));
sw.Reset();
sw.Start();
query = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 120 && item.Key < 210)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw.Stop();
Console.WriteLine(String.Format("Query for > 120 and < 210 : {0} ms, Total Items: {1}",
sw.ElapsedMilliseconds, query.Count<KeyValuePair<int, int>>()));
sw.Reset();
sw.Start();
query = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 104757500 && item.Key < 104857200)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw.Stop();
Console.WriteLine(String.Format("Query for > 104.757.500 and < 104.857.200 : {0} ms, Total Items: {1}",
sw.ElapsedMilliseconds, query.Count<KeyValuePair<int, int>>()));
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<int, int> base01 = new Dictionary<int, int>(26214400);
Dictionary<int, int> base02 = new Dictionary<int, int>(26214400);
Dictionary<int, int> base03 = new Dictionary<int, int>(26214400);
Dictionary<int, int> base04 = new Dictionary<int, int>(26214400);
for (int i = 0; i < 26214400; i++) { base01.Add(i, i); }
for (int i = 26214401; i < 52428800; i++) { base02.Add(i, i); }
for (int i = 52428801; i < 78643200; i++) { base03.Add(i, i); }
for (int i = 78643201; i < 104857600; i++) { base04.Add(i, i); }
int maxVal = 104857600; // 104.857.600
Dictionary<int, int> srcDict = new Dictionary<int, int>(maxVal);
for (int i = 1; i < 26214401; i++)
{
try
{
srcDict.Add(base01[i], base01[i]);
srcDict.Add(base04[78643201 + i], base04[78643201 + i]);
srcDict.Add(base03[52428801 + i], base03[52428801 + i]);
srcDict.Add(base02[26214401 + i], base02[26214401 + i]);
}
catch
{
//:-(
}
}
Stopwatch sw1 = new Stopwatch();
sw1.Start();
IEnumerable<KeyValuePair<int, int>> query1 = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 21214401 && item.Key < 58428801)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw1.Stop();
Console.WriteLine(String.Format("Query for > 21.214.401 and < 58.428.801: {0} ms, Total Items: {1:000,000,000}",
sw1.ElapsedMilliseconds, query1.Count<KeyValuePair<int,int>>()));
Stopwatch sw2 = new Stopwatch();
sw2.Start();
IEnumerable<KeyValuePair<int, int>> query2 = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 52428701 && item.Key < 59428801)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw2.Stop();
Console.WriteLine(String.Format("Query for > 52.428.701 and < 59.428.801 : {0} ms, Total Items: {1:000,000,000}",
sw2.ElapsedMilliseconds, query2.Count<KeyValuePair<int, int>>()));
Stopwatch sw3 = new Stopwatch();
sw3.Start();
IEnumerable<KeyValuePair<int, int>> query3 = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 16214401 && item.Key < 29214401)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw3.Stop();
Console.WriteLine(String.Format("Query for > 16.214.401 and < 29.214.401 : {0} ms, Total Items: {1:000,000,000}",
sw3.ElapsedMilliseconds, query3.Count<KeyValuePair<int, int>>()));
Stopwatch sw4 = new Stopwatch();
sw4.Start();
IEnumerable<KeyValuePair<int, int>> query4 = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 90565 && item.Key < 79428801)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw4.Stop();
Console.WriteLine(String.Format("Query for > 90.565 and < 79.428.801 : {0} ms, Total Items: {1:000,000,000}",
sw4.ElapsedMilliseconds, query4.Count<KeyValuePair<int, int>>()));
Console.ReadLine();
}
}
Output1 писал(а):Fill Dictionary (0 to 104.857.600 items): 1313 ms.
Query for > 256.789 and < 1.024.789 : 6 ms, Total Items: 767999
Query for > 120 and < 210 : 0 ms, Total Items: 89
Query for > 104.757.500 and < 104.857.200 : 0 ms, Total Items: 99699
Output2 писал(а):Query for > 21.214.401 and < 58.428.801: 6 ms, Total Items: 037 214 395
Query for > 52.428.701 and < 59.428.801 : 0 ms, Total Items: 007 000 097
Query for > 16.214.401 and < 29.214.401 : 0 ms, Total Items: 012 999 997
Query for > 90.565 and < 79.428.801 : 0 ms, Total Items: 079 338 229
kanut писал(а):Да, а я вначале подумал, что это List, просто сортированный
FireFenix писал(а):Опять ты пристал. Человек не говорит зачем ему нужно, а так же возможно он использует массив для хранения индексного дерева некоторых элементов.
С учётом большого количества элементов, выборки диапазонов, сложных условий и удобности лучше использовать СУБД
kanut писал(а):Кстати, 10 млн. записей это максимум, а начинаться коллекция будет с 1 элемента.
FireFenix писал(а):У тебя развитая телепатия и ты знаешь, что для человека быстро?
FireFenix писал(а):И что за lb n? Может имелось ввиду log2 n?
FireFenix писал(а):И где тут не правда? я же не сказал, что SortedList это и есть Dictionary, а я сказал - смесь
По пунктам:FireFenix писал(а):SortedList это смесь List + Dictionary. Имея индексы можно делать поиск хешу и перебирать потом диапазон индексов, но как и SortedDictionary при каждой вставке выполняется сравнение элемента с уже имеющимися в худшем случаю дающее O(log2 n), т.е. если на перебор всего массива требуется 200мс, то для вставки 100мс
kanut писал(а):Спасибо всем за помощь, буду делать функцию выборки с SortedList.
Dmitriy2003 писал(а):Не принимая в расчет все вышесказанное - меня результат вполне устраивает, а почему вас нет
Dmitriy2003 писал(а):Output1 писал(а):Fill Dictionary (0 to 104.857.600 items): 1313 ms.
Query for > 256.789 and < 1.024.789 : 6 ms, Total Items: 767999
Query for > 120 and < 210 : 0 ms, Total Items: 89
Query for > 104.757.500 and < 104.857.200 : 0 ms, Total Items: 99699
Qwertiy писал(а):Что-то не так в твоих замерах. И уж точно не стоит использовать Linq там, где важно быстро получить результат.
Dmitriy2003 писал(а):Не принимая в расчет все вышесказанное - меня результат вполне устраивает, а почему вас нет
Dmitriy2003 писал(а):
- Код: Выделить всё
sw.Reset();
sw.Start();
start = DateTime.Now;
IEnumerable<KeyValuePair<int, int>> query = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 256789 && item.Key < 1024789)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
sw.Stop();
Console.WriteLine(String.Format("Query for > 256.789 and < 1.024.789 : {0} ms {2}, Total Items: {1}",
sw.ElapsedMilliseconds, query.Count<KeyValuePair<int, int>>(), (DateTime.Now - start).TotalMilliseconds));
Qwertiy писал(а):Ты понимаешь как это работает?
IEnumerable<KeyValuePair<int, int>> query = srcDict
.Where<KeyValuePair<int, int>>(item => item.Key > 256789 && item.Key < 1024789)
.Select<KeyValuePair<int, int>, KeyValuePair<int, int>>(item => item);
Dmitriy2003 писал(а):а вот синтаксис задел за живое
IEnumerable<KeyValuePair<int, int>> query = srcDict
.Where(item => item.Key > 256789 && item.Key < 1024789)
.Select(item => item);
IEnumerable<KeyValuePair<int, int>> query = from item in srcDict where item.Key > 256789 && item.Key < 1024789 select item;
Qwertiy писал(а):Кстати, а зачем тут последний select в таком виде?
Qwertiy писал(а):А ещё можно так:
- Код: Выделить всё
IEnumerable<KeyValuePair<int, int>> query = from item in srcDict where item.Key > 256789 && item.Key < 1024789 select item;
Dmitriy2003 писал(а):меня результат вполне устраивает, а почему вас нет
Qwertiy писал(а): kanut писал(а):Да, а я вначале подумал, что это List, просто сортированный
Ну так ты был прав
Qwertiy писал(а):При этом каждая вставка будет выполняться за O(n)
kanut писал(а):Коллекция заполнится только один раз (и при каждой загрузке программы естественно, значениями подряд), а потом будут только выборки диапазонов.
Qwertiy писал(а):Тогда зачем же ты говорил, что добавление элементов есть?
Тогда, конечно, SortedList. Или даже просто массив. И бинарный поиск.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10