Помогите с логикой быстрого поиска в списке

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
Всем привет!
Нужна помощь в правильной реализации проекта: есть список в текстовом формате размером 1.5гб, в проекте необходимо сравнивать значения переменных со строками в списке максимально быстро и выдавать ок или false.
Пробовал размещать список на RAM диске в оперативке и делать поиск через c# :
C#:
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = project.Lists["spisok"];
// ищем в каждой строчке в списке
lock(SyncObjects.ListSyncer)
{
    for(int i=0; i < sourceList.Count; i++)
    {
        // читаем строку из списка
        var str = sourceList[i];
        // проверяем содержание текста в строке, если есть совпадение возвращаем "yes"
        if (str.Contains(textContains))
        {

return "yes";
}
}
}
// если ничего не нашли возвращаем "no"
return "no";
При таком решении поиск очень долгий, более 5 секунд на запрос, что ну никак не устраивает...
Подскажите по какому пути пойти? Копать в строну БД или есть еще какие-то решения?

Всем заранее спасибо.
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 689
Баллы
113

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
мне кажется 5 с. на 1.5 гига это нормально. быстрее списков только БД.
Спасибо, но для моих задач - это очень долго... нужна скорость во много раз больше.. На какой БД лучше реализовывать? Что будет быстрее всего?
 

SergSh

Client
Регистрация
10.05.2017
Сообщения
541
Благодарностей
395
Баллы
63
Попробуй этот код. Хотя идея перебора больших списков не очень, темболее сравнивая списки через contains
C#:
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = project.Lists["spisok"];
List<string> sourceList = new List<string>(project.Lists["list"]);
lock(SyncObjects.ListSyncer)
{
    var res = sourceList.AsParallel().FirstOrDefault(x => x.Contains(textContains));
   if(res != null) return "yes";
}
return "no";
 
  • Спасибо
Реакции: Rimen

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
поиск по полному совпадению? Просто проверка есть ли строка или нет?
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
Бинарный поиск тут должен быть идеален. Правда я никогда им не пользовался в списках
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
Бинарный поиск тут должен быть идеален. Правда я никогда им не пользовался в списках
можно попробовать загружать список в хэшсет, а там по обычному контэинс
Спасибо!
Вы не могли бы подсказать в зенке как код применить? не силен в коде c# :(
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
Спасибо!
Вы не могли бы подсказать в зенке как код применить? не силен в коде c# :(
C#:
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = new HashSet<string>(project.Lists["spisok"]);

if (sourceList.Contains(textContains)) return "yes";

return "no";
Попробуй так. Скажи, будет ли быстрее
 

Alexmd

Client
Регистрация
10.12.2018
Сообщения
1 021
Благодарностей
1 385
Баллы
113
теория: распоточить поиск.
основной поток перебирает список по первому чару и при совпадении передает другим фоновым потокам для дальнейшего сравнения.
Надеюсь, полет моей мысли понятен? Я не имею ввиду поток зенки.
 

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 943
Благодарностей
4 336
Баллы
113
Я использую indexOf вместо Contains. Ходят легенды, что такой подход немного быстрее.
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 689
Баллы
113
теория: распоточить поиск.
основной поток перебирает список по первому чару и при совпадении передает другим фоновым потокам для дальнейшего сравнения.
Надеюсь, полет моей мысли понятен? Я не имею ввиду поток зенки.
ну щас отпишется автор о скорости метода, если не увеличиться то наверно к этому алгоритму и придем.
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
Спасибо всем, сейчас буду пробовать! :-)
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
C#:
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = new HashSet<string>(project.Lists["spisok"]);

if (sourceList.Contains(textContains)) return "yes";

return "no";
Попробуй так. Скажи, будет ли быстрее
на 3-4 секунды дольше работает, чем код в стартпосте...
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
теория: распоточить поиск.
основной поток перебирает список по первому чару и при совпадении передает другим фоновым потокам для дальнейшего сравнения.
Надеюсь, полет моей мысли понятен? Я не имею ввиду поток зенки.
Можно подробнее? Не понял поток вашей мысли)
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
на 3-4 секунды дольше работает, чем код в стартпосте...
C#:
int t1 = Environment.TickCount;
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = new HashSet<string>(project.Lists["spisok"]);

int dt1 = Environment.TickCount - t1;

sourceList.Contains(textContains);

int dt2 = Environment.TickCount - t1 - dt1;

return string.Format("{0} --- {1}", dt1, dt2);
какие цифры в ответ выведет этот код?
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
C#:
int t1 = Environment.TickCount;
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = new HashSet<string>(project.Lists["spisok"]);

int dt1 = Environment.TickCount - t1;

sourceList.Contains(textContains);

int dt2 = Environment.TickCount - t1 - dt1;

return string.Format("{0} --- {1}", dt1, dt2);
какие цифры в ответ выведет этот код?
7407 --- 0
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 689
Баллы
113

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
C#:
int t1 = Environment.TickCount;
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var temp = project.Lists["spisok"].OrderBy(x => x);

int dt1 = Environment.TickCount - t1;

var sourceList = new HashSet<string>(temp);

int dt2 = Environment.TickCount - t1 - dt1;

sourceList.Contains(textContains);

int dt3 = Environment.TickCount - t1 - dt1 - dt2;

return string.Format("{0} --- {1} --- {2}", dt1, dt2, dt3);
а этот?

поиск мгновенный, а загрузка списка 7.4 с. интересно.
время на формирование множества. А поиск там не перебором идёт
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
C#:
int t1 = Environment.TickCount;
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var temp = project.Lists["spisok"].OrderBy(x => x);

int dt1 = Environment.TickCount - t1;

var sourceList = new HashSet<string>(temp);

int dt2 = Environment.TickCount - t1 - dt1;

sourceList.Contains(textContains);

int dt3 = Environment.TickCount - t1 - dt1 - dt2;

return string.Format("{0} --- {1} --- {2}", dt1, dt2, dt3);
а этот?


время на формирование множества. А поиск там не перебором идёт
этот код ушел в выполнение и не заканчивается.. ждал пару минут, пришлось завершить процесс PM.
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
этот код ушел в выполнение и не заканчивается.. ждал пару минут, пришлось завершить процесс PM.
прости) Тогда ещё момент. Можешь отсортировать свой файл по возрастанию? Есть вероятность, что по отсортированному тот 1й код сработает быстрее
 

Koqpe

Client
Регистрация
23.12.2014
Сообщения
1 100
Благодарностей
649
Баллы
113
C#:
// Добавить в using
using System.Threading.Tasks;

// Снипет:
string textContains = project.Variables["id"].Value;
string status = "no";
IZennoList sourceList = project.Lists["spisok"];
Parallel.ForEach<string>(sourceList, el => {
    if (el == textContains){
    status = "yes";
    }
});
return status;
 

Koqpe

Client
Регистрация
23.12.2014
Сообщения
1 100
Благодарностей
649
Баллы
113
Для замера времени выполнения можно так:
C#:
// В самое начало снипета
var timer = System.Diagnostics.Stopwatch.StartNew();

// Перед return status;
timer.Stop();
var ts = TimeSpan.FromSeconds(timer.ElapsedMilliseconds/1000);
project.SendInfoToLog(string.Format("Время выполнения проекта: {0} д. {1} ч. {2} мин. {3} сек.", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds), true);
 
  • Спасибо
Реакции: ZULI и doc

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
прости) Тогда ещё момент. Можешь отсортировать свой файл по возрастанию? Есть вероятность, что по отсортированному тот 1й код сработает быстрее
в файле буквенно-цифровые строки, они все разные, даже не знаю, чем отсортировать такое и такого объема...
 

planeta

Client
Регистрация
01.09.2015
Сообщения
113
Благодарностей
44
Баллы
28
Для замера времени выполнения можно так:
C#:
// В самое начало снипета
var timer = System.Diagnostics.Stopwatch.StartNew();

// Перед return status;
timer.Stop();
var ts = TimeSpan.FromSeconds(timer.ElapsedMilliseconds/1000);
project.SendInfoToLog(string.Format("Время выполнения проекта: {0} д. {1} ч. {2} мин. {3} сек.", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds), true);
Прописал Using
Собрал код так:
C#:
var timer = System.Diagnostics.Stopwatch.StartNew();
string textContains = project.Variables["id"].Value;
string status = "no";
IZennoList sourceList = project.Lists["spisok"];
Parallel.ForEach<string>(sourceList, el => {
    if (el == textContains){
    status = "yes";
    }
});
return status;
timer.Stop();
var ts = TimeSpan.FromSeconds(timer.ElapsedMilliseconds/1000);
project.SendInfoToLog(string.Format("Время выполнения проекта: {0} д. {1} ч. {2} мин. {3} сек.", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds), true);
Время выполнения почему то нет в логе, хотя код выполняется. Работает по моим замерам где то на секунду быстрее кода из стартпоста. За это спасибо, но, это все равно очень долго...
 

Koqpe

Client
Регистрация
23.12.2014
Сообщения
1 100
Благодарностей
649
Баллы
113
Остановку таймера выведи до return status;
C#:
var timer = System.Diagnostics.Stopwatch.StartNew();

string textContains = project.Variables["id"].Value;
string status = "no";
IZennoList sourceList = project.Lists["spisok"];
Parallel.ForEach<string>(sourceList, el => {
    if (el == textContains){
    status = "yes";
    }
});

timer.Stop();
var ts = TimeSpan.FromSeconds(timer.ElapsedMilliseconds/1000);
project.SendInfoToLog(string.Format("Время выполнения проекта: {0} д. {1} ч. {2} мин. {3} сек.", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds), true);

return status;
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)