Уведомления

Группа в Telegram: присоединиться

#1 Апрель 17, 2018 14:09:57

driveman
Зарегистрирован: 2018-02-28
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

Доброго всем времени суток.

Имеется список словарей. Элементы списка теоретически должны быть уникальны, в терминологии БД - по нескольким полям (ключам словарей), допустим они будут называться key1, key2, key3.

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

Как это сделать питонично, например, с помощью генераторов списков?

Офлайн

#2 Апрель 18, 2018 12:07:14

ZerG
Зарегистрирован: 2012-04-05
Сообщения: 1446
Репутация: +  42  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

Напишите конкретные примеры словарей с даннымии укажите какая конкретно уникальность вас интересует

Офлайн

#3 Апрель 18, 2018 16:34:50

driveman
Зарегистрирован: 2018-02-28
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

Примерно так (19.04.2018 по-другому отформатировал код, кажется, так легче читается):

 l = [
    {'key1': 'home',      'key2': 'word',      'key3': 'that',      'key4': 842268745},
    # не уникален, у эл-та с индексом 3 такие же значения:
    {'key1': 'secret',    'key2': 'terrible',  'key3': 'phone',     'key4': 654},
    {'key1': 'aback',     'key2': 'tippy',     'key3': 'fireworks', 'key4': 123},
    # не уникален, у эл-та с индексом 1 такие же значения:
    {'key1': 'secret',    'key2': 'terrible',  'key3': 'phone',     'key4': 23689633},
    {'key1': 'murage',    'key2': 'sweep',     'key3': 'transmit',  'key4': 9875},
    # не уникален, у эл-тов с индексами 8 и 9 такие же значения:
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 632125},
    {'key1': 'cognitive', 'key2': 'coin',      'key3': 'jubilant',  'key4': 96},
    {'key1': 'keel',      'key2': 'lately',    'key3': 'serf',      'key4': 622144},
    # не уникален, у эл-тов с индеками 1 и 9 такие же значения:
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 77},
    # не уникален, у эл-тов с индексами 1 и 8 такие же значения:
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 253},
]
Надо найти словари со значениями, неуникальными по ключам key1, key2, key3. В данном примере они выделены в комментариях. Значения по ключу key4 при этом могут быть любыми, они не учитывается.

Отредактировано driveman (Апрель 19, 2018 15:54:02)

Офлайн

#4 Апрель 18, 2018 19:39:22

vic57
Зарегистрирован: 2015-07-07
Сообщения: 776
Репутация: +  106  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

примерно так

 >>> l = [
    {'key1': 'home',      'key2': 'word',      'key3': 'that',      'key4': 842268745},
    {'key1': 'secret',    'key2': 'terrible',  'key3': 'phone',     'key4': 654},       # не уникален, у эл-та с индексом 3 такие же значения
    {'key1': 'aback',     'key2': 'tippy',     'key3': 'fireworks', 'key4': 123},
    {'key1': 'secret',    'key2': 'terrible',  'key3': 'phone',     'key4': 23689633},  # не уникален, у эл-та с индексом 1 такие же значения
    {'key1': 'murage',    'key2': 'sweep',     'key3': 'transmit',  'key4': 9875},
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 632125},    # не уникален, у эл-тов с индексами 8 и 9 такие же значения
    {'key1': 'cognitive', 'key2': 'coin',      'key3': 'jubilant',  'key4': 96},
    {'key1': 'keel',      'key2': 'lately',    'key3': 'serf',      'key4': 622144},
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 77},        # не уникален, у эл-тов с индеками 1 и 9 такие же значения
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 253},       # не уникален, у эл-тов с индексами 1 и 8 такие же значения
]
>>> lst = sorted([list(i.items()) for i in l])
>>> from itertools import groupby
>>> g = groupby(lst,key = lambda x: (x[0],x[1],x[2]))
>>> for k,v in g:
	l = list(v)
	if len(l) > 1: print(l)
	
[[('key1', 'beagle'), ('key2', 'cloistral'), ('key3', 'close'), ('key4', 77)], [('key1', 'beagle'), ('key2', 'cloistral'), ('key3', 'close'), ('key4', 253)], [('key1', 'beagle'), ('key2', 'cloistral'), ('key3', 'close'), ('key4', 632125)]]
[[('key1', 'secret'), ('key2', 'terrible'), ('key3', 'phone'), ('key4', 654)], [('key1', 'secret'), ('key2', 'terrible'), ('key3', 'phone'), ('key4', 23689633)]]
>>> 

Онлайн

#5 Апрель 19, 2018 16:10:06

driveman
Зарегистрирован: 2018-02-28
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

vic57
примерно так
Не получается. Дело в том, что вот эта строка:
 groupby(lst,key = lambda x: (x[0],x[1],x[2]))
будет стабильно выдавать нужный результат только в том случае, если значения в словарях будут всегда идти в том же порядке, что и при создании списка словарей, ведь группировка идет по инексам, а не по ключам. Но, так как словарь не упорядочен - каждый раз словари выводятся упорядоченными по-разному. Вот как у меня получалось. Был взят участок кода только с сортировкой:
 l = [
    {'key1': 'home',      'key2': 'word',      'key3': 'that',      'key4': 842268745},
    # не уникален, у эл-та с индексом 3 такие же значения:
    {'key1': 'secret',    'key2': 'terrible',  'key3': 'phone',     'key4': 654},
    {'key1': 'aback',     'key2': 'tippy',     'key3': 'fireworks', 'key4': 123},
    # не уникален, у эл-та с индексом 1 такие же значения:
    {'key1': 'secret',    'key2': 'terrible',  'key3': 'phone',     'key4': 23689633},
    {'key1': 'murage',    'key2': 'sweep',     'key3': 'transmit',  'key4': 9875},
    # не уникален, у эл-тов с индексами 8 и 9 такие же значения:
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 632125},
    {'key1': 'cognitive', 'key2': 'coin',      'key3': 'jubilant',  'key4': 96},
    {'key1': 'keel',      'key2': 'lately',    'key3': 'serf',      'key4': 622144},
    # не уникален, у эл-тов с индеками 1 и 9 такие же значения:
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 77},
    # не уникален, у эл-тов с индексами 1 и 8 такие же значения:
    {'key1': 'beagle',    'key2': 'cloistral', 'key3': 'close',     'key4': 253},
]
lst = sorted([list(i.items()) for i in l])
for elem in lst:
    print(elem)

Каждый раз получившиеся кортежи выдавались упорядоченными по разному, например, первый случай (key1, key2, key4, key3):
 [('key1', 'aback'), ('key2', 'tippy'), ('key4', 123), ('key3', 'fireworks')]
[('key1', 'beagle'), ('key2', 'cloistral'), ('key4', 77), ('key3', 'close')]
[('key1', 'beagle'), ('key2', 'cloistral'), ('key4', 253), ('key3', 'close')]
[('key1', 'beagle'), ('key2', 'cloistral'), ('key4', 632125), ('key3', 'close')]
[('key1', 'cognitive'), ('key2', 'coin'), ('key4', 96), ('key3', 'jubilant')]
[('key1', 'home'), ('key2', 'word'), ('key4', 842268745), ('key3', 'that')]
[('key1', 'keel'), ('key2', 'lately'), ('key4', 622144), ('key3', 'serf')]
[('key1', 'murage'), ('key2', 'sweep'), ('key4', 9875), ('key3', 'transmit')]
[('key1', 'secret'), ('key2', 'terrible'), ('key4', 654), ('key3', 'phone')]
[('key1', 'secret'), ('key2', 'terrible'), ('key4', 23689633), ('key3', 'phone')]

второй случай (key3, key1, key4, key2):
 [('key3', 'close'), ('key1', 'beagle'), ('key4', 77), ('key2', 'cloistral')]
[('key3', 'close'), ('key1', 'beagle'), ('key4', 253), ('key2', 'cloistral')]
[('key3', 'close'), ('key1', 'beagle'), ('key4', 632125), ('key2', 'cloistral')]
[('key3', 'fireworks'), ('key1', 'aback'), ('key4', 123), ('key2', 'tippy')]
[('key3', 'jubilant'), ('key1', 'cognitive'), ('key4', 96), ('key2', 'coin')]
[('key3', 'phone'), ('key1', 'secret'), ('key4', 654), ('key2', 'terrible')]
[('key3', 'phone'), ('key1', 'secret'), ('key4', 23689633), ('key2', 'terrible')]
[('key3', 'serf'), ('key1', 'keel'), ('key4', 622144), ('key2', 'lately')]
[('key3', 'that'), ('key1', 'home'), ('key4', 842268745), ('key2', 'word')]
[('key3', 'transmit'), ('key1', 'murage'), ('key4', 9875), ('key2', 'sweep')]
Ну и так далее.

Но в любом случае спасибо, уже есть вероятность, что смогу довести ваш пример до рабочего состояния

Офлайн

#6 Апрель 19, 2018 18:53:54

vic57
Зарегистрирован: 2015-07-07
Сообщения: 776
Репутация: +  106  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

формат был тот какой вы дали
решаемо рекурсией сортировка->группировка

 >>> d = {'k1':'v4','k4':'v3','k3':'v2','k2':'v1',}
>>> sorted(d.items(),key=lambda x: x[0])
[('k1', 'v4'), ('k2', 'v1'), ('k3', 'v2'), ('k4', 'v3')]
>>> sorted(d.items(),key=lambda x: x[1])
[('k2', 'v1'), ('k3', 'v2'), ('k4', 'v3'), ('k1', 'v4')]
>>> 
в моем коде одну строку поменять надо
 >>> lst = sorted(sorted(i.items(),key=lambda x:x[0]) for i in l])

Отредактировано vic57 (Апрель 19, 2018 19:00:47)

Онлайн

#7 Апрель 20, 2018 01:46:00

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 5708
Репутация: +  517  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

driveman
Несмотря на то, что теоретически элементы должны быть уникальными - на практике это может быть не так.
Надо сделать функцию, которая принимает список элементов и возвращает n-ки индексов вхождений.
1 2 3 -> (0) (1) (2)
1 1 1 2 -> (0 1 2) (3)
1 2 3 4 4 3 2 1 -> (0 7) (1 6) (2 5) (3 4)
1 2 3 4 1 2 3 4 1 2 3 4 5 -> (0 4 7) (1 5 8) (2 6 9) (3 7 10) (12)

А потом ты в эту функцию подаёшь просто списки всех значений каждого ключа и по возвращённым n-кам видишь весь расклад по повторяющимся элементам по каждому ключу. Индексы будут совпадать со словарями, после этого уже принимаешь решение, что делать дальше.

Короче, общий принцип: если видишь сложную, запутанную задачу, то чаще всего она требует просто чего-то недостающего для решения - какую-то дополнительную функцию, которой нет.

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



Офлайн

#8 Апрель 20, 2018 07:35:41

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 3155
Репутация: +  174  -
Профиль   Отправить e-mail  

Поиск дубликатов в списке словарей

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

 key4 =
{
( 'home', 'word','that'): 842268745,
( 'secret', 'terrible','phone'):  654,
....
}
Имена ключей вам не особо нужны. Если хочется их оставить то используйте namedtuple. В такую структуру не вставишь не уникальные значения ключи key1,key2,key3.

Перенос подходов принятых в реляционных базах приводит к уродливым решениям.



Отредактировано doza_and (Апрель 20, 2018 07:36:58)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version