Найти - Пользователи
Полная версия: Поиск повторяющихся элементов в большом кол-ве списков
Начало » Python для экспертов » Поиск повторяющихся элементов в большом кол-ве списков
1 2 3
artexcite
Здравствуйте.
Начну с небольшого лирического отступления.
У меня есть база данных MyQSL, хранящаяся на обычном хостинге. Выбор использования БД хостинга основывался на возможности удаленного подключения к БД из разных мест. К тому же, хостинг уже имелся до начала разработки проекта.
В базе имеется определенная, интересующая нас, таблица, которая имеет несколько столбцов. Один из столбцов содержит списки элементов, т.е. в ячейке хранятся данные следующего вида:
 [123456, 23456789, 3456789, 41234567, 5678909, 64563223, 74456785, 8456788]
Списки имеют длину от 7 тыс. до 100 тыс. элементов. Также хотелось бы отметить, что таблица имеет 3 500 строк (получается 3 500 списков) и соответственно строки в таблицу добавляются.
Для информации:
- столбец имеет тип данных mediumtext
- на данный момент таблица весит 800 Мб.
Ну, а теперь к сути:
Мне необходимо собрать из всех списков, элементы, которые повторяются 3 и более раз в разных списках, т.е. >=3.
Изначально я пытался сделать следующим образом:
1. Сделать выгрузку из всех строк таблицы из БД.
2. Из строки извлечь данные одной нас интересующей ячейки, т.е. список.
3. Склеить все 3 500 списков.
4. Выполнить что-то вроде:
 i for i in set(mylist) if mylist.count(i) >= 3
Тут у меня сразу возникало много проблем:
1. Все сразу выгрузить не получилось, т.к. хостинг разорвал со мной соединение из-за таймаута. Слишком много сразу хочу – 800 Мб (сделал цикл по выгрузки по 20 строк и решил эту проблему).
2. Когда начал склеивать списки, то появилась другая проблема. Пусть у нас есть «глобальный список», хранящий в себе 3 500 списков. Так вот этот «глобальный список» стал настолько большим, что у меня не хватило 10Гб ОЗУ, т.к. в итоге «глобальный список» должен содержать около 200 миллионов элементов.
Посоветуйте и подскажите хоть что-нибудь, что мне поможет. Может у кого-то есть идеи по организации хранения данных в базе и поиску повторяющихся значений.
Готов пересмотреть всю концепцию моего неработающего алгоритма.
py.user.next
artexcite
Мне необходимо собрать из всех списков, элементы, которые повторяются 3 и более раз в разных списках
Непонятно, что нужно выбрать (двусмысленно написано).

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

Когда пишешь списки используй тег code, так как квадратные скобки и их содержимое вырезаются (в твоём сообщении вырезались).
Rodegast
> Один из столбцов содержит списки элементов

У тебя не нормализованная схема данных. Тебе нужно твой список хранить в отдельной таблице. Тогда можно будет решить твою задачу с помощью 1 запроса.
artexcite
py.user.next
Приведи конкретный пример на как бы выгруженных списках. Представь, что ты уже выгрузил списки, и у тебя получилось три каких-то списка, вот на них и приведи пример, что и по какому принципу из них выбирать.
Ок.
Пост выше подправил.
Приведу простенький пример.
 list_1 = [1,2,3,4,5,8,8]
list_2 = [3,4,5,6,7]
list_3 = [3,4,5,6,7,8]
list_all = list_1 + list_2 + list_3
print(*(i for i in set(list_all) if list_all.count(i) >= 3))
Вывод:
>> 3 4 5 8
artexcite
Rodegast
У тебя не нормализованная схема данных. Тебе нужно твой список хранить в отдельной таблице. Тогда можно будет решить твою задачу с помощью 1 запроса.

Да все верно, БД у меня не приведена к нормальной форме, например, ко 2 форме.
Я думал об этом, но если я буду хранить каждый элемент списка в отдельной ячейке строки, то у меня получится около 200 миллионов строк таблицы. В будущем строк будет еще больше.
Тут конечно удобно. Можно сделать один запрос к БД и получить нужный результат:
 SELECT name_colum FROM name_table GROUP BY name_colum HAVING COUNT(name_colum) >= 2
При написании такого алгоритма я столкнулся с проблемами:

1. Скрипт начал работать очень долго, т.к. очень много строк в таблице.

2. Не смог реализовать запрос:
 INSERT INTO name_table (name_colum) VALUES ("Значение 1"), ("Значение 2"), ("Значение N")
В запросе кол-во значений равно количеству элементов списка и количество элементов в списках всегда разные. Вот и получается, что я не смог сделать такой простой INSERT с динамическим кол-вом значений в VALUES.

3. Один и тот же список ежедневно изменяется и кол-во элементов может как уменьшится, так и увеличиться, следовательно, перед вставкой необходимо сделать проверку на присутствие или отсутствие элемента списка в БД.
Если я начну делать такую проверку каждого элемента списка, то мне придется сделать, например, 7 000 запросов в БД если список длиной 7 000 элементов и если:
- этот элемент есть в БД, то его заново не вставлять
- этого элемента нет, то вставлять
Запрос такого рода не подойдёт:
 INSERT INTO name_table (id_list, id_list_item) VALUES ("Значение", "Значение") ON DUPLICATE KEY UPDATE id_list = "Значение"
Также нужно удалить из БД те элементы, которые отсутствуют в новом списке.

Если вы подскажите как мне решить эти 3 проблемы, то я буду вам благодарен.

Вроде пытался понятно изложить свои мысли, если что задавайте вопросы. С радостью отвечу.

P.S. Если честно я не знаю, как будет вести себя таблица БД если в ней будет 200 миллионов строк.
py.user.next
artexcite
Пост выше подправил.
Приведу простенький пример.
Надо брать каждый список и потом брать каждый элемент списка.
Элементы сохраняются в сквозной словарь, где ключ - число из списка, а значение - количество встретившихся таких чисел.
Когда набирается нужное количество вхождений, число выдаётся на выход.

То есть не надо ничего выгружать, сохранять, соединять, всё делается на лету.
Rodegast
> у меня получится около 200 миллионов строк таблицы

А что ты там хранишь если не секрет?

> 2. Не смог реализовать запрос:

У тебя должна быть вставка нескольких строк.

> P.S. Если честно я не знаю, как будет вести себя таблица БД если в ней будет 200 миллионов строк.

Мускул поведёт себя хреново, лучше используй PostgreSQL. Если в у тебя изначально заложена денормализация, то ИХМО нужно смотреть на NoSQL.
Rodegast
> То есть не надо ничего выгружать, сохранять, соединять, всё делается на лету.

Там 3500 списков, в каждом 100 000 элементов. У тебя памяти на это не хватит.
py.user.next
Rodegast
Там 3500 списков, в каждом 100 000 элементов. У тебя памяти на это не хватит.
Там память вообще не нужна, так как всё на итераторах.
FishHook
Rodegast
Там 3500 списков, в каждом 100 000 элементов. У тебя памяти на это не хватит.
подтверждаю, не хватит
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB