Сравнить две таблицы?

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
Всем привет.
Есть способ быстро сравнить две таблицы?
Сравнение идет по id в столбце "А", там лежат id товаров.
Нужно пропускать старые товары и добавлять в таблицу только новые. Например, которые пользователь завел в личный кабинет.
Не хочется просто индусским способом через два for делать))
 

doc

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

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
дубль
 

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
в чем же индусскость?
Сейчас так сделал:
C#:
for(int m=0;m>=GoodsInCab.RowCount;m++){
                      
    string OldId = OldFileTable.GetCell("A",m);

    if(OldId==ElmsIdTxt){
        project.SendInfoToLog("Строка с id - " + ElmsIdTxt + " уже добавлена, пропускаем ее",true);
    }else{
        GoodsInCab.AddRow(ElmsIdTxt + ";" + NamesList + ";" + GoodsPrice + ";" + TimesElms + ";" + MnfElems + ";" + ElmsStatus + ";" + ViewsElms + ";" + ElmsUrlTxt);
    }
}
Хочу, чтобы в процессе парсинга сразу сравнивались id старой и новой таблиц в столбце A, если строка которая сейчас парсится уже добавлена в новую таблицу, то она просто не пишется.
Просто, когда бот обходит таблицу на 800 строк, время работы значительно увеличивается. Если просто парсинг записывал таблицу на 800 строк за 5-6 минут, то тут ок часа возится)
 

Alexmd

Client
Регистрация
10.12.2018
Сообщения
1 021
Благодарностей
1 383
Баллы
113
В принципе неправильный подход.
Правильно будет не формировать новую таблицу при новом парсинге, а налету сравнивать добавлена ли id в таблицу.
Там, где происходит парсинг, надо сразу проверить существует ли в таблице этот id и только потом или парсить все остальные значения или пропускать эту страницу.
Отпадает необходимость существования новой таблицы, сокращаются ресурсы и время на парсинг.
C#:
foreach(string id in idList)//допустим, у нас перебор id из списка
/*перед тем как парсить все остальное и писать в итоговую таблицу, надо убедиться, что это имеет смысл*/
if(table.GetColumn("A").IndexOf(id) < 0){//если меньше 0, то в таблице нет строки с этим id
    /* тут весь парсинг*/
}
else{//иначе пропускаем этот id
    continue;
}
 
  • Спасибо
Реакции: DenisK

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
В принципе неправильный подход.
Правильно будет не формировать новую таблицу при новом парсинге, а налету сравнивать добавлена ли id в таблицу.
Там, где происходит парсинг, надо сразу проверить существует ли в таблице этот id и только потом или парсить все остальные значения или пропускать эту страницу.
Отпадает необходимость существования новой таблицы, сокращаются ресурсы и время на парсинг.
C#:
foreach(string id in idList)//допустим, у нас перебор id из списка
/*перед тем как парсить все остальное и писать в итоговую таблицу, надо убедиться, что это имеет смысл*/
if(table.GetColumn("A").IndexOf(id) < 0){//если меньше 0, то в таблице нет строки с этим id
    /* тут весь парсинг*/
}
else{//иначе пропускаем этот id
    continue;
}
кстати, да. Не подумал об этом) спасибо. Как сделаю, выложу решение
кстати, откуда у вас Index в этом месте? из коробки не вижу такого. Или что-то еще надо подключить?
 
Последнее редактирование:

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63

nicanil

Client
Регистрация
06.03.2016
Сообщения
2 242
Благодарностей
1 804
Баллы
113
Может тут Intersect имелось в виду?
table.GetColumn возвращает IEnumerable у которого действительно нет IndexOf, но он есть у списка. Можно немного модифицировать код от Alexmd:
C#:
var column = table.GetColumn("A").ToList();
foreach(string id in idList)//допустим, у нас перебор id из списка
/*перед тем как парсить все остальное и писать в итоговую таблицу, надо убедиться, что это имеет смысл*/
if(column.IndexOf(id) < 0){//если меньше 0, то в таблице нет строки с этим id
    /* тут весь парсинг*/
}
else{//иначе пропускаем этот id
    continue;
}
Но, я думаю, что лучше будет использовать такой подход:
C#:
var column = table.GetColumn("A");
foreach(string id in idList)//допустим, у нас перебор id из списка
/*перед тем как парсить все остальное и писать в итоговую таблицу, надо убедиться, что это имеет смысл*/
if(column.FirstOrDefault(item => item == id) == null){//если равно null, то в колонке нет такого значения.
    /* тут весь парсинг*/
}
else{//иначе пропускаем этот id
    continue;
}
Замеры не проводил, но думаю второй вариант будет быстрей, т.к. не тратится время на конвертацию IEnumerable в List.
 

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
использовать такой подход:
Спасибо. Пока сделал по такой схеме:
1. из первой таблицы все id скинул во внутренний список
2. в процессе парсинга сделал сравнение новых id со старыми, если id == новому, то строку не пишем, если нет - то да. Те так пишутся только свежие строки из ЛК в таблицу
3. очистил внутренний список, чтобы id не сохранялись там
Пожалуй, что-то более оптимальное я не придумаю, дальше БД надо использовать только
 

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
но думаю второй вариант будет быстрей
Все нормально пишется, единственно - не понятно, почему при переносе строк методом SetCell, строка где формат времени установлен как H:mm:ss, время переносится в таком формате: 31.12.1899 9:00:00, причем даты в первой таблице нет, только время
 

nicanil

Client
Регистрация
06.03.2016
Сообщения
2 242
Благодарностей
1 804
Баллы
113
Все нормально пишется, единственно - не понятно, почему при переносе строк методом SetCell, строка где формат времени установлен как H:mm:ss, время переносится в таком формате: 31.12.1899 9:00:00, причем даты в первой таблице нет, только время
Могу тут уже немного напутать, но опишу как это понимаю я.

Это особенность Excel. В исходной таблице эти ячейки имеют формат "Время". И дата в них тоже подразумевается, но не отображается. 31.12.1899 что-то вроде нулевой даты в Excel. А ZennoPoster, судя по всему, эту нулевую дату видит (даже просто привязав файл к Таблице и посмотрев на содержимое Таблицы через внутренний просмоторщик видно, что эти ячейки уже содержат 31.12.1899).

Костыль конечно, но можно менять 31.12.1899 на пустоту, если она в начале строки.
 
  • Спасибо
Реакции: artsmm

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 110
Благодарностей
195
Баллы
63
Могу тут уже немного напутать, но опишу как это понимаю я.

Это особенность Excel. В исходной таблице эти ячейки имеют формат "Время". И дата в них тоже подразумевается, но не отображается. 31.12.1899 что-то вроде нулевой даты в Excel. А ZennoPoster, судя по всему, эту нулевую дату видит (даже просто привязав файл к Таблице и посмотрев на содержимое Таблицы через внутренний просмоторщик видно, что эти ячейки уже содержат 31.12.1899).

Костыль конечно, но можно менять 31.12.1899 на пустоту, если она в начале строки.
примерно так и сделал, регуляркой убираю дату, оставляю только время. Тогда время берется в таком формате: H:mm:ss через Parse.Exact
 

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