Нужна помощь в поиске строки в списке c#

arbplv

Client
Регистрация
28.03.2020
Сообщения
373
Реакции
23
Баллы
18
Добрый вечер.
Задача.
Спарсить данные с сайта, который обновляется где-то раз в 2-3 секунды и положить в список все эти данные. Данные должны быть уникальными.
Я сделал бесконечный цикл через while с задержкой в 100 мс, System.Threading.Thread.Sleep(100).
Все данные складываю в список и на выходе у меня получается, типа такого:
10:05:59:508 строка 1
10:05:59:854 строка 1
10:06:00:157 строка 2
10:06:00:506 строка 2
10:06:00:854 строка 1
10:06:01:202 строка 3
10:06:01:481 строка 3
10:06:01:772 строка 3
10:06:02:181 строка 4
10:06:02:473 строка 3
10:06:03:002 строка 2
10:06:03:351 строка 2
10:06:03:588 строка 5
10:06:03:868 строка 5
10:06:04:106 строка 3
10:06:04:384 строка 2
10:06:04:648 строка 5
10:06:04:914 строка 1
10:06:05:202 строка 4
10:06:05:720 строка 1

Если посмотреть на данные то там есть дубли, мне нужно как то проверять на наличие дублей, и в случае нахождения дублей нужно не заносить эти данные в список.
Данные заношу с помощью переменной, сначала создал HtmlElementCollection и циклом выдергиваю нужные мне данные и заношу в список. К примеру, переменную назовем var а список InfoList. Получается мне нужно проверять есть ли переменная var в списке InfoList.
Подскажите как это сделать?
Через .Contains не подходит, тк мне нужно точное сравнение. Что то запутался с синтаксисом, выручайте плиз. У меня мысли такие, но чет не могу до конца сообразить:
идет код и в переменной на этом этапе уже лежат данные
var = "проверяемые данные";
//делаем цикл из всех строчек что лежат уже в списке, чтобы проверить каждую
for (int i =0; i<InfoList.Count(); i++)
{
if(var == InfoList ) // если есть повторение, то сбрасываем цикл и ничего не проверяем
{break;}

else if(var != InfoList && i == (InfoList.Count - 1)) // если не равно всем значениям и все перебрали (i равен максимальному значению) то записываем строчку в конец
{InfoList.Add(var);}

}

Но чет не работает, по разному пробовал, понимаю что для многих простая задача, но я чет не соображу уже...
нужно проверить все строчки и если нет совпадений, занести эти данные.
Спс за помощь и время что прочитали мою писанину...
 
метод .Contains для списка ищет точное совпадение
Если у меня 3 строки;
слово1 слово2
слово1 слово2 слово3
слово1 слово2 слово3 слово4
И через .Contains мы ищем 2 строку (слово1 слово2 слово3), то этот метод выдаст нам и 2 и 3 строку.
 
Если через метод, то наиболее близкий для меня, это наверное .Equals, но сильно большой разницы с == я не знаю, т.к. не так хорошо знаю C#. Тут вопрос как это написать, логикой то я понимаю что нужно сделать. Проверить переменную на соответствие с каждой строчкой списка, и если нет совпадения, записать. Вопрос наверное больше по синтаксису... Вот думаю...
 
Если у меня 3 строки;
слово1 слово2
слово1 слово2 слово3
слово1 слово2 слово3 слово4
И через .Contains мы ищем 2 строку (слово1 слово2 слово3), то этот метод выдаст нам и 2 и 3 строку.
я говорю о методе списка, а не тестовой переменной. Он не выдаёт строки, он отдаёт true или false в зависимости от того, есть строка в списке или нет
InfoList.Contains
 
  • Спасибо
Реакции: arbplv
C#:
Развернуть Свернуть Копировать
var list = итоговый_список;
var portion = порция_спаршенных_данных;
foreach(string str in portion)
    if(list.IndexOf(str) >= 0)
        list.Add(str);
 
  • Спасибо
Реакции: arbplv
10:05:59:508 строка 1
10:05:59:854 строка 1
10:06:00:157 строка 2
10:06:00:506 строка 2
10:06:00:854 строка 1
10:06:01:202 строка 3
10:06:01:481 строка 3
10:06:01:772 строка 3
10:06:02:181 строка 4
10:06:02:473 строка 3
10:06:03:002 строка 2
10:06:03:351 строка 2
10:06:03:588 строка 5
10:06:03:868 строка 5
10:06:04:106 строка 3
10:06:04:384 строка 2
10:06:04:648 строка 5
10:06:04:914 строка 1
10:06:05:202 строка 4
10:06:05:720 строка 1
Если каждая строка в твоем списке содержит в начале дату тогда нужно сначала от нее избавиться. примерно так:
Поиск дубля строки в списке без учета даты в начале строки:
Развернуть Свернуть Копировать
List<string> InfoList = new List<string> {
                "10:05:59:508 строка 1",
                "10:05:59:854 строка 1",
                "10:06:00:157 строка 2",
                "10:06:00:506 строка 2",
                "10:06:00:854 строка 1",
                "10:06:01:202 строка 3",
                "10:06:01:481 строка 3",
                "10:06:01:772 строка 3",
                "10:06:02:181 строка 4",
                "10:06:02:473 строка 3",
                "10:06:03:002 строка 2",
                "10:06:03:351 строка 2",
                "10:06:03:588 строка 5",
                "10:06:03:868 строка 5",
                "10:06:04:106 строка 3",
                "10:06:04:384 строка 2",
                "10:06:04:648 строка 5",
                "10:06:04:914 строка 1",
                "10:06:05:202 строка 4",
                "10:06:05:720 строка 1"
            };
string searchString = "строка 1";
if (!InfoList.Any(x => Regex.Match(x, "(?<=[0-9]{3} ).*").Value == searchString))// (?<=[0-9]{3} ).* - эта регулярка удаляет дату и пробел после нее потом идет сравнение строк.
   InfoList.Add(searchString);
 
  • Спасибо
Реакции: arbplv
C#:
Развернуть Свернуть Копировать
var list = итоговый_список;
var portion = порция_спаршенных_данных;
foreach(string str in portion)
    if(list.IndexOf(str) >= 0)
        list.Add(str);
Можешь пояснить строку list.IndexOf(str) >= 0,
Вот на пальцах и переменной, а не списке.
string str1 = "Hello world!";
string str2 = "lo";
int pos = str1.IndexOf(str2);
// pos = 3
.IndexOf возвращает индекс с отсчетом от нуля первого вхождения указанного символа Юникода или строки в пределах данного экземпляра. Получается в нашем случае, если есть вхождение, то вернется номер строки где есть это вхождение, а это больше 0 и запишется наша новая строка. Правильно я тебя понял?
 
Можешь пояснить строку list.IndexOf(str) >= 0,
Вот на пальцах и переменной, а не списке.
string str1 = "Hello world!";
string str2 = "lo";
int pos = str1.IndexOf(str2);
// pos = 3
.IndexOf возвращает индекс с отсчетом от нуля первого вхождения указанного символа Юникода или строки в пределах данного экземпляра. Получается в нашем случае, если есть вхождение, то вернется номер строки где есть это вхождение, а это больше 0 и запишется наша новая строка. Правильно я тебя понял?
Верно.


Так ищется полное совпадение строки в списке, просто чуток пошустрее, чем перебором в цикле.
Но, если надо вырезать дату из строки, то тут больше подойдет пример со сравнением, предложенный выше, потому что нецелесообразно преобразовывать весь список, чтобы искать там по индексу.
Я сперва подумал, что дата - это тоже результат парсинга, а не время занесения строки в список, вот и предложил, а потом присмотрелся, но было поздно...
 
Если каждая строка в твоем списке содержит в начале дату тогда нужно сначала от нее избавиться. примерно так:
Поиск дубля строки в списке без учета даты в начале строки:
Развернуть Свернуть Копировать
List<string> InfoList = new List<string> {
                "10:05:59:508 строка 1",
                "10:05:59:854 строка 1",
                "10:06:00:157 строка 2",
                "10:06:00:506 строка 2",
                "10:06:00:854 строка 1",
                "10:06:01:202 строка 3",
                "10:06:01:481 строка 3",
                "10:06:01:772 строка 3",
                "10:06:02:181 строка 4",
                "10:06:02:473 строка 3",
                "10:06:03:002 строка 2",
                "10:06:03:351 строка 2",
                "10:06:03:588 строка 5",
                "10:06:03:868 строка 5",
                "10:06:04:106 строка 3",
                "10:06:04:384 строка 2",
                "10:06:04:648 строка 5",
                "10:06:04:914 строка 1",
                "10:06:05:202 строка 4",
                "10:06:05:720 строка 1"
            };
string searchString = "строка 1";
if (!InfoList.Any(x => Regex.Match(x, "(?<=[0-9]{3} ).*").Value == searchString))// (?<=[0-9]{3} ).* - эта регулярка удаляет дату и пробел после нее потом идет сравнение строк.
   InfoList.Add(searchString);
с регуляркой понятно, а вот дальше не очень, давай разберем поподробнее.
1. проверяемая строка у нас лежит в переменной searchString
2. с помощью вот этого кусочка Regex.Match(x, "(?<=[0-9]{3} ).*").Value мы получаем чистую строку без времени. А что за х фигурирует? если посмотреть документацию то
Regex(string sourceString, string sourceRegex,) дальнейшие перегрузки не используем. Получается х это номер строки которая получается из нашего списка, так?
3. также не понятно и вот этот сравнение (x => зачем мы так сравниваем?
4. дальше мы ставим отрицание !InfoList... , а чем отличаться будет если напишем вот так ...Value != search...
Заранее извини если вопросы покажутся глупыми, спс
 
Верно.


Так ищется полное совпадение строки в списке, просто чуток пошустрее, чем перебором в цикле.
Но, если надо вырезать дату из строки, то тут больше подойдет пример со сравнением, предложенный выше, потому что нецелесообразно преобразовывать весь список, чтобы искать там по индексу.
Я сперва подумал, что дата - это тоже результат парсинга, а не время занесения строки в список, вот и предложил, а потом присмотрелся, но было поздно...
я конечную строку собираю из 3х переменных, могу с датой, могу без даты. Мне очень важна скорость, прям очень))), потому и время в миллисекундах. IndexOf вот этот метод он быстрее ищет, нежели перебор в цикле, верно? Я вообще думал чистить список каждые например 1000 строк, чтобы ускорить процесс. Данные мне нужны буквально несколько часов, потом можно их удалить.
 
Верно.


Так ищется полное совпадение строки в списке, просто чуток пошустрее, чем перебором в цикле.
Но, если надо вырезать дату из строки, то тут больше подойдет пример со сравнением, предложенный выше, потому что нецелесообразно преобразовывать весь список, чтобы искать там по индексу.
Я сперва подумал, что дата - это тоже результат парсинга, а не время занесения строки в список, вот и предложил, а потом присмотрелся, но было поздно...
а метод InfoList.Contains не будет еще быстрее IndexOf ?
 
также не понятно и вот этот сравнение (x => зачем мы так сравниваем?
В моем варианте используется System.Linq (IndexOf из той же оперы )), Contains туда же) Так вот Метод Any у списка смотрит есть ли в списке какое либо совпадение в соответствии с предикатом. Где предикатом является лямда ф-ция. ( x => x == searchString). Посмотри на ютубе ролики по запросу C# LINQ примеры )). Там много интересного.

Относительно времени проверки Все решения которые тут написаны работают одинаково быстро. В моем варианте будет обрабатываться условие быстрее если не использовать регулярки вообще. ( x => x == searchString).

дальше мы ставим отрицание !InfoList... , а чем отличаться будет если напишем вот так ...Value != search...
Возвращаемым значением предиката)), с точки зрения логики ни чем.

а метод InfoList.Contains не будет еще быстрее IndexOf ?
Так же в твоем кейсе метод Contains использовать не вариант так как он проверяет вхождение подстроки в строку. Ты уже писал об этом:
И через .Contains мы ищем 2 строку (слово1 слово2 слово3), то этот метод выдаст нам и 2 и 3 строку.

А тебе нужно сравнивать 2 строки целиком это делается через ==

в борьбе за скорость:

C#:
Развернуть Свернуть Копировать
List<string> searchStringsList = new List<string>
            {
                "10:05:59:508 строка 1",
                "10:06:00:506 строка 2"
            };
            // В случае параллельной обработки данных придется использовать ConcurrentQueue - это потокобезопасный список так скажем ))
            //Если использовать простой List тогда будет ошибка параллельного доступа к данным, а использование lock все усилия по увеличению скорости сведет на нет
            ConcurrentQueue<string> InfoList = new ConcurrentQueue<string>();
            //Используем TPL
            searchStringsList.AsParallel().ForAll(
                //предикат где Х это строка из списка searchStringsList
                x => {
                    if (InfoList.Any(
                        //второй предикат обозначим за Y, это строка из списка InfoList)
                        y => y != x)
                    )
                    {
                        //если не нашли точного вхождения данных то добавляем строку в список результата
                        InfoList.Enqueue(x);
                    }
                    }
                );
 
  • Спасибо
Реакции: SHILY, arbplv и Alexmd
Вопрос решился с помощью метода .IndexOf.
Всем спасибо за внимание!
 

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