Анализ данных: как найти дубликаты в массиве

Mar 24, 2023 22:10

Окружение: операционная система «Windows 10», программа-оболочка «PowerShell» версии 7, скрипт «Get-LiveJournal».

Тестирую скрипт «Get-LiveJournal». На небольшом журнале «vbgtut» со 147 постами скрипт работал без каких-либо вопросов. Теперь я запустил его на журнале «ilyachalov», в котором пишу этот пост. На момент запуска скрипта в журнале «ilyachalov» было 1273 поста, если верить числу постов, указанному в профиле. Исправил пару мелких ошибок и скрипт отработал на журнале «ilyachalov» без ошибок, получилось выгрузить все посты 13 порциями (13 текстовых файлов с телами HTTP(S)-ответов сервера ЖЖ). Скрипт справился с этой работой за 20 секунд:



Вроде бы, всё хорошо. Однако, как видно на иллюстрации выше, скрипт выгрузил всего 1280 постов. Это число не сходится с числом постов, указанным в профиле - 1273.

Сначала я подумал, что, возможно, в число постов, указанное в профиле журнала, не включаются посты с ограниченным доступом (только для друзей, групп друзей, личные) и/или посты с отметкой « Не добавлять в ленты друзей и RSS». Я поэкспериментировал с созданием таких постов в журнале «vbgtut» и выяснил, что это предположение неверное. Число постов, указанное в профиле, включает и посты с ограниченным доступом, и посты с отметкой «Не добавлять в ленты друзей и RSS». То есть число постов, указанное в профиле, всегда показывает реальное число постов в журнале (также это число не зависит от того, зашли ли вы в ЖЖ под своей учетной записью или зашли как анонимный читатель).

После этого я подумал, что, возможно, моя реализация алгоритма выгрузки всех постов журнала неидеальна и некоторые посты попадают в итоговые текстовые файлы по нескольку раз (дубликаты).

Подготовка таблицы постов для анализа

Чтобы проверить предположение о наличии дубликатов в результатах работы скрипта, я загрузил итоговые текстовые файлы в программе-оболочке «PowerShell» в отдельные переменные, преобразовал их в хеш-таблицы, которые преобразовал в таблицы постов, а последние сложил в одну таблицу постов. Как это сделать, я подробно описывал в ряде постов ранее (например, тут). Вот какого вида таблица постов получилась:

$table.Length

1280

$table | Select-Object -First 5 |
Format-Table @{e="num";w=3}, @{e="itemid";w=6}, @{e="anum";w=4},
@{e="eventtime";w=19}, @{e="subject";w=16},
@{e="url";w=11}, @{e="event";w=16}

num itemid anum eventtime subject url event
--- ------ ---- --------- ------- --- -----
25 25 235 2010-06-09 17:39:00 Как изучить про… 6635.html %D0%9E%D0%B1%D1…
64 65 72 2011-02-01 14:09:00 Государство … 16712.html 3-8%20%D0%B4%D0…
14 14 52 2010-04-10 14:50:00 О курении 3636.html %D0%90%D1%80%D1…
16 16 15 2010-04-13 00:16:00 Об идеалистах и… 4111.html %D0%9E%D0%B1%D1…
49 50 192 2010-12-06 00:01:00 «Велотрен… 12992.html %D0%94%D0%BB%D0…

Для последующего поиска дубликатов постов достаточно проанализировать только одну колонку этой таблицы - «itemid» (содержит идентификаторы постов). Выделяю эту колонку в отдельный массив чисел для анализа (этой же командой я сортирую элементы массива в порядке возрастания):

"" + ($table.itemid | Sort-Object)

1 2 3 4 5 6 7 8 9 10 11 12 13 ... 1271 1272 1273 1274 1275 1276

В блоке кода выше я не стал приводить все значения массива, а привел только 13 первых значений и 6 последних, иначе эти числа заняли бы слишком много места в посте, что было бы неудобно для чтения.

Поиск дубликатов в массиве с помощью электронных таблиц

В принципе, для этого можно использовать любую современную программу, предоставляющую функционал электронных таблиц. Мне удобно работать с «Google Таблицами», которые я храню на «Google Диске» (drive.google.com), поэтому буду показывать на их примере.

Копирую массив идентификаторов постов в первую ячейку электронной таблицы:



Выбираю в главном меню пункт «Данные - Разделить текст на столбцы». Программа запрашивает, что используется в качестве разделителя. Выбираю из списка пункт «Пробел». Идентификаторы постов оказываются разбиты по ячейкам первой строки электронной таблицы:



В электронной таблице мне удобнее работать с данными в вертикальном положении, а не в горизонтальном, как сейчас. Копирую первую строку электронной таблицы в буфер обмена, а затем вставляю в ячейку A2 из контекстного меню с помощью пункта «Специальная вставка - Поменять местами строки и столбцы». Удаляю первую строку электронной таблицы. В результате идентификаторы постов оказываются разбиты по ячейкам первого столбца электронной таблицы:



В первую ячейку второго столбца (B) электронной таблицы вставляю формулу =СТРОКА(A1) (функция «СТРОКА» возвращает номер текущей строки электронной таблицы) и соглашаюсь на предложенное программой автозаполнение, в результате программа автоматически копирует эту формулу для всех ячеек колонки «B», для которых есть значение в колонке «A».

В первую ячейку третьего столбца (C) электронной таблицы вставляю формулу =A1-B1 и соглашаюсь на предложенное программой автозаполнение по уже описанному выше принципу.

Теперь можно прокручивать электронную таблицу вниз и искать места, в которых число в третьей колонке будет изменяться. Причиной такого изменения будут либо дубликаты идентификаторов постов, либо «прорехи» в нумерации постов, вызванные постами, которые автор журнала в какой-то момент удалил. Например, вот один из найденных дубликатов:



Всего я нашел семь дубликатов постов (идентификаторы 105, 315, 413, 513, 812, 1014 и 1213). Этим объясняется разница между числом загруженных постов (1280) и числом постов, указанным в профиле журнала (1273). Таким образом, моя реализация загрузки всех постов журнала действительно является неидеальной и содержит некую ошибку, которую еще предстоит найти.

Также я нашел три «прорехи» в нумерации постов (идентификаторы 216, 298 и 704). Этим объясняется разница между последним использованным идентификатором поста (1276) и числом постов, указанным в профиле журнала (1273).

Поиск дубликатов в массиве с помощью PowerShell

Впрочем, вышеописанный способ - это, скорее, кустарщина. У меня мало опыта работы с электронными таблицами. Наверняка там можно придумать что-нибудь поизящнее. А в программе-оболочке «PowerShell» для полученной выше таблицы постов идентификаторы постов, к которым в таблице есть дубликаты, можно получить, например, вот так, одной командой:

"" + ($table | Group-Object -Property "itemid" | Where-Object {$_.Count -gt 1}).Name

105 315 413 513 812 1014 1213

Если эту команду немного изменить, можно получить таблицу с задвоившимися постами:

$tableD = ($table | Group-Object -Property "itemid" | Where-Object {$_.Count -gt 1}).Group
$tableD | Format-Table @{e="num";w=3}, @{e="itemid";w=6}, @{e="anum";w=4},
@{e="eventtime";w=19}, @{e="subject";w=16},
@{e="url";w=11}, @{e="event";w=16}

num itemid anum eventtime subject url event
--- ------ ---- --------- ------- --- -----
100 105 250 2011-11-18 22:49:00 КВН 2011: треть… 27130.html %D0%98%D0%B3%D1…
2 105 250 2011-11-18 22:49:00 КВН 2011: треть… 27130.html %D0%98%D0%B3%D1…
100 315 254 2018-12-25 03:33:00 Авторские канал… 80894.html %D0%9F%D0%B5%D1…
6 315 254 2018-12-25 03:33:00 Авторские канал… 80894.html %D0%9F%D0%B5%D1…
100 413 124 2020-01-17 03:57:00 C++: чтение объ… 105852.html %D0%94%D0%B0%D0…
2 413 124 2020-01-17 03:57:00 C++: чтение объ… 105852.html %D0%94%D0%B0%D0…
100 513 19 2020-08-31 04:59:00 Проектирование … 131347.html %D0%9D%D0%B0%D1…
7 513 19 2020-08-31 04:59:00 Проектирование … 131347.html %D0%9D%D0%B0%D1…
100 812 57 2021-11-15 16:08:00 MDN Web Docs: к… 207929.html %D0%9F%D1%80%D0…
3 812 57 2021-11-15 16:08:00 MDN Web Docs: к… 207929.html %D0%9F%D1%80%D0…
100 1014 126 2022-04-05 10:58:00 VS Code Docs: у… 259710.html %D0%9E%D1%80%D0…
4 1014 126 2022-04-05 10:58:00 VS Code Docs: у… 259710.html %D0%9E%D1%80%D0…
100 1213 60 2023-01-03 01:27:00 Что такое «пост… 310588.html %D0%A0%D0%B5%D1…
17 1213 60 2023-01-03 01:27:00 Что такое «пост… 310588.html %D0%A0%D0%B5%D1…

По колонке «num» можно уже предварительно сделать вывод, что в моей реализации алгоритма выгрузки всех постов журнала что-то не в порядке с концевыми условиями моментов времени получаемых порций постов (номер 100 - это последний пост в очередной порции из 100 постов, возвращаемой сервером ЖЖ).

Причину ошибки я буду искать позже. Данный пост посвящен поиску дубликатов в массиве. В этом плане имеет смысл обратить внимание на командлет «Group-Object», работа с которым продемонстрирована выше.

Инструмент, Образование, Программирование, ЖЖ

Previous post Next post
Up