Как оптимально сравнить две таблицы значений?

Как оптимально сравнить две таблицы значений?

По результатам текущего обсуждения выпущена статья Лучшие методы сравнения таблиц значений .

В ней задача обобщена на случай составного ключа. Для этого все функции переписаны. Также изменено представления результатов сравнения. Это я сделал на свой страх и риск. Возражения принимаются.

Поэтому возможны помарки и может оказаться необходимой перепроверка. Если есть желание - подключайтесь. Обнаружены интересные артефакты, связанные, вероятно с местом хранения строк таблицы значений. Они еще требуют объяснения.

Несколько методов осталось "в запасе". Например, использование нового объекта 8.3, позволяющего рассчитать хэш-функцию. Ну и разные доработки свертки.

Но зато выводы получились очень четкими. Каждому методу нашлось свое место. Буквально таблицу решений по выбору метода можно построить. Посмотрю на результаты обсуждения (если оно будет) и сделаю это.

  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти

У меня была похожая задачка. Могу посоветовать выгрузить ТЗ в табличные части и сравнивать их запросом

// Функция сравнивает ТЧ док "ОприходованиеТоваров" и ТЧ док "ЗаказНаПроизводство" (с учетом всех корректировок) // Если они одинаковые вернет Истину в противном случае Ложь Функция ПроверкаЗаполненияОприходования(ОприходованиеТоваров,ЗаказНаПроизводство)

Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ | Подсчет.Номенклатура, | Подсчет.ЕдиницаИзмерения, | Подсчет.Количество, | СУММА(Подсчет.Счетчик) КАК СчетчикМин, | СУММА(Подсчет.Счетчик) КАК СчетчикМакс |ИЗ | (ВЫБРАТЬ | ПотребностиЗаказовНаПроизводство.Номенклатура КАК Номенклатура, | ПотребностиЗаказовНаПроизводство.ЕдиницаИзмерения КАК ЕдиницаИзмерения, | ПотребностиЗаказовНаПроизводство.Количество КАК Количество, | 0.5 КАК Счетчик | ИЗ | РегистрНакопления.ПотребностиЗаказовНаПроизводство КАК ПотребностиЗаказовНаПроизводство | ГДЕ | ПотребностиЗаказовНаПроизводство.ЗаказНаПроизводство.Ссылка = &ЗаказНаПроизводство | | ОБЪЕДИНИТЬ ВСЕ | | ВЫБРАТЬ | ОприходованиеТоваровТовары.Номенклатура, | ОприходованиеТоваровТовары.ЕдиницаИзмерения, | ОприходованиеТоваровТовары.Количество, | 0.5 | ИЗ | Документ.ОприходованиеТоваров.Товары КАК ОприходованиеТоваровТовары | ГДЕ | ОприходованиеТоваровТовары.Ссылка = &ОприходованиеТоваров) КАК Подсчет | |СГРУППИРОВАТЬ ПО | Подсчет.Номенклатура, | Подсчет.Количество, | Подсчет.ЕдиницаИзмерения |ИТОГИ | МИНИМУМ(СчетчикМин), | МАКСИМУМ(СчетчикМакс) |ПО | ОБЩИЕ"; Запрос.УстановитьПараметр("ОприходованиеТоваров", ОприходованиеТоваров); Запрос.УстановитьПараметр("ЗаказНаПроизводство", ЗаказНаПроизводство); Выборка = Запрос.Выполнить().Выбрать(); Выборка.Следующий();

ТЧ_Совпадают = (Выборка.СчетчикМин = Выборка.СчетчикМакс И Выборка.СчетчикМин = 1);

  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти

Который раз меня удивляет отсутствие метода отбора " НЕ ", а было бы так просто.

1) сравнил размеры таблиц (количество строк) 2) меньшую запихал в отбор 3) из второй выбрал строки методом " НЕ ОТБОР "

получил строки которых нет в первой таблице

П.С. Правда в первой таблице могут быть строки которых нет во второй. Поэтому просьба к автору топика

Конкретизировать критерии сравнения.

Например: - Найти строки котрые совпадают в обоих таблицах - Найти строки которые отличаются в обоих таблицах - Найти строки которые "добавились" в одной из таблиц -.

  • Скопировать ссылку
  • Перейти

Время массива с добавлением 136 мсек. Время массива по индексу 133 мсек. Время соответствия 76 мсек.

  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти

340+ Если так модифицировать то слияние на некоторых тестах обходит Хэш

  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти

(342) ildarovich, двойная свертка при приведении к Соответствии резко падает (нелинейно растет время выполнения). Код:

  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти
  • Скопировать ссылку
  • Перейти

(347) ildarovich, Я выбрал такой результат как показательный в теле функции, а не как функциональный. Функцианал как мне кажется, полностью покрывающий практику ECUD (equil, create, update, delete):

1. "Равны" ли таблицы? Для срабатывания триггеров. 2. Что удалили? Для зачистки связанных данных. 3. Что изменили? Для перепроведения 4. Что добавили? Для генерации чего-либо. 5. Одинаковые элементы нужны для LRu кэша, но как то к 1С не применимо.

  • Скопировать ссылку
  • Перейти

(349) awk, еще раз говорю: вопрос тоньше!

Сначала исключим психологические моменты: 1) Я не воспринимаю двойную свертку как свой метод - этот метод общеизвестный и первый какой приходит в голову. Я всего лишь его компактно записал, чтобы не было никаких потерь (YanTSys не все сделал для этого). 2) Я очень люблю соответствие (ХэшМап) и всюду его применяю - я за него так же болею. 3) Использование соответствия вместо индекса в этой задаче - это ваша и очень ценная находка, достойная отдельной публикации. В другой ветке народ уже интересовался - я эту вашу находку уже упоминал. Особенно, если речь будет идти о составных ключах [K1][K2]. [KN]. Правда, пока мне непонятно как красиво обрабатывать отсутствие ключа в очередном измерении.

Теперь о нашем соревновании. Углубившись в задачу, я очень многое про нее понял, над чем первоначально не задумывался. И, в частности, вот что: Результат, включающий соответствия Одинаковые[УказательНаСтрокуВТаблице1] -> УказательНаСтрокуВТаблице2 и Измененные[УказательНаСтрокуВТаблице1] -> УказательНаСтрокуВТаблице2 пользователю не требуется. Это промежуточные данные. Которые получаются как побочный эффект по ходу работы вашего метода. Если пользователь спрашивает: какие строки изменились, то ему нельзя отвечать: изменились строки, расположенные в оперативной памяти по адресу 0x5555 и по адресу 0x7777. Ему это будет непонятно и не нужно. Но если он спросит: а сколько полей в этой записи изменилось, какие поля изменились, на сколько изменились поля, то на все эти содержательные вопросы и многие другие можно будет ответить, получив и имея эти соответствия. Но, если задача ставится именно так: разместить в памяти структуру для быстрого ответа на такие вопросы, то решение становится безальтернативным . Если это спрашивается, то нужно использовать ХэшМап и только ХэшМап. - Никакого соревнования нет и быть не может! (слияние тоже не перемещает строки в памяти, но тратит больше отдельных операций и при реализации на 1С, видимо, проигрывает). Так что если хотите допустить других участников, то разрешайте ответы, не содержащие УказательНаСтрокуВТаблице1 и УказательНаСтрокуВТаблице2, а содержащие КлючСтрокиВТаблице1 и КлючСтрокиВТаблице2. Тогда и будет соревнование.

  • Скопировать ссылку
  • Перейти

Вызвало улыбку. Неужели кто-то считает общеизвестные алгоритмы своим изобретением?

:))) Не моя. Типовое решение в другой среде. В Яве HashMap - это очень популярная коллекция. При добавлении 5 строчек в которую превращается во вполне эффективный LRU кэш.

Еще раз: результат функции - не принципиален. Например я бы в рабочей среде немного изменил сигнатуру вызова сравнения, дабы передать "посетителя". А вставки заменил с:

  • Скопировать ссылку
  • Перейти

(363) awk, ну, мне показалось, что спор сворачивает в сторону: чей метод лучше. Чей - не в смысле изобретен, а кто предложил. Не так - ну и хорошо.

Попыток - исключений в коде интуитивно сторонюсь. Для меня это что-то типа goto. Хотя, может и зря. Нужно на скорость проверить.

Запихивать в ответ по второму разу полные строки?

Ну а если результат функции не принципиален, почему всем не взять "общительную" коллекцию типа массива или той же таблицы значений. Вы же за это даже баллы накидывать собирались. У меня дурацкая тяга к симметрии и мне в этой задаче нравится результат в виде таблицы значений. Типа на вход подали ТЗ и на выходе ТЗ. Такая матричная арифметика. Только одна структура.

Ну или по крайней мере исключить указатели на строки. Тогда все будут на равных. В общем, мое единственное условие - исключить указатели, то есть тип данных СтрокаТаблицыЗначений.

📎📎📎📎📎📎📎📎📎📎