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

  • Автор темы Автор темы planeta
  • Дата начала Дата начала

planeta

Client
Регистрация
01.09.2015
Сообщения
129
Реакции
52
Баллы
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 секунд на запрос, что ну никак не устраивает...
Подскажите по какому пути пойти? Копать в строну БД или есть еще какие-то решения?

Всем заранее спасибо.
 
мне кажется 5 с. на 1.5 гига это нормально. быстрее списков только БД.
Спасибо, но для моих задач - это очень долго... нужна скорость во много раз больше.. На какой БД лучше реализовывать? Что будет быстрее всего?
 
Попробуй этот код. Хотя идея перебора больших списков не очень, темболее сравнивая списки через 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
Бинарный поиск тут должен быть идеален. Правда я никогда им не пользовался в списках
 
Бинарный поиск тут должен быть идеален. Правда я никогда им не пользовался в списках
можно попробовать загружать список в хэшсет, а там по обычному контэинс
Спасибо!
Вы не могли бы подсказать в зенке как код применить? не силен в коде c# :(
 
Спасибо!
Вы не могли бы подсказать в зенке как код применить? не силен в коде c# :(
C#:
Развернуть Свернуть Копировать
// берем из переменной текст, который надо искать
var textContains = project.Variables["id"].Value;
// получаем список, в котором будем искать
var sourceList = new HashSet<string>(project.Lists["spisok"]);

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

return "no";

Попробуй так. Скажи, будет ли быстрее
 
теория: распоточить поиск.
основной поток перебирает список по первому чару и при совпадении передает другим фоновым потокам для дальнейшего сравнения.
Надеюсь, полет моей мысли понятен? Я не имею ввиду поток зенки.
 
теория: распоточить поиск.
основной поток перебирает список по первому чару и при совпадении передает другим фоновым потокам для дальнейшего сравнения.
Надеюсь, полет моей мысли понятен? Я не имею ввиду поток зенки.
ну щас отпишется автор о скорости метода, если не увеличиться то наверно к этому алгоритму и придем.
 
Спасибо всем, сейчас буду пробовать! :)
 
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 секунды дольше работает, чем код в стартпосте...
 
теория: распоточить поиск.
основной поток перебирает список по первому чару и при совпадении передает другим фоновым потокам для дальнейшего сравнения.
Надеюсь, полет моей мысли понятен? Я не имею ввиду поток зенки.
Можно подробнее? Не понял поток вашей мысли)
 
на 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);

какие цифры в ответ выведет этот код?
 
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
 
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 с. интересно.
время на формирование множества. А поиск там не перебором идёт
 
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.
 
этот код ушел в выполнение и не заканчивается.. ждал пару минут, пришлось завершить процесс PM.
прости) Тогда ещё момент. Можешь отсортировать свой файл по возрастанию? Есть вероятность, что по отсортированному тот 1й код сработает быстрее
 
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;
 
Для замера времени выполнения можно так:
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
прости) Тогда ещё момент. Можешь отсортировать свой файл по возрастанию? Есть вероятность, что по отсортированному тот 1й код сработает быстрее
в файле буквенно-цифровые строки, они все разные, даже не знаю, чем отсортировать такое и такого объема...
 
Для замера времени выполнения можно так:
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);
Время выполнения почему то нет в логе, хотя код выполняется. Работает по моим замерам где то на секунду быстрее кода из стартпоста. За это спасибо, но, это все равно очень долго...
 
Остановку таймера выведи до 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;
 

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