Update:
Привет. Мой вопрос в том, как я могу сравнить значения словаря для равенства. Дополнительная информация о моем словаре:
значения каждого ключа являются вложенными списками → f.e.
[[1,0], [2,0], [3,1]]
длина значений для каждого ключа arent одинакова, поэтому может быть, что номер сеанса 1 имеет больше значений, а затем номер сеанса 2
order_session = {1: [[100,0], [22,1], [23,2]], 10: [100,0], [232,0], [10,2], [11,2]], 22: [[5,2], [23,2],....]...}
Моя цель:
Шаг 1: для сравнения значений сеанса номер 1 со значениями всех остальных номеров сеанса в словаре для равенства
Шаг 2: возьмите следующий номер сеанса и сравните значения с другими значениями других номеров сеансов и т.д. - наконец, мы оцениваем стоимость каждого сеанса
Шаг 3: сохраните результат в списке f.e. output = [[100,0], [23,2],...] или output = [(100,0), (23,2),...]
Спасибо, что помогли мне.
Обновление 2
Благодарим вас за вашу помощь и советы по изменению вложенного списка списков в список кортежей, которые лучше справляются с этим.
Я предпочитаю решение Боаза Янива;) Мне также нравится использование коллекций. Counter()... неудачно, что я использую 2.6.4 (Counter работает в версии 2.7), возможно, я иногда меняю 2,7.
Если ваш словарь длинный, вы хотите использовать наборы для лучшей производительности (поиск уже встречающихся значений в списках будет довольно медленным):
def get_repeated_values(sessions):
known = set()
already_repeated = set()
for lst in sessions.itervalues():
session_set = set(tuple(x) for x in lst)
repeated = (known & session_set) - already_repeated
already_repeated |= repeated
known |= session_set
for val in repeated:
yield val
sessions = {1:[[100,0],[22,1],[23,2]],10:[[100,0],[232,0],[10,2],[11,2]],22:[[5,2],[23,2]]}
for x in get_repeated_values(sessions):
print x
Я также предлагаю (опять же по соображениям производительности) вставлять кортежи внутри ваших списков вместо списков, если вы не собираетесь менять их на лету. Код, который я разместил здесь, будет работать в любом случае, но это будет быстрее, если значения уже являются кортежами.
order_session = {1:[[100,0],[22,1],[23,2]],10:[[100,0],[232,0],[10,2],[11,2]],22:[[5,2],[23,2],[80,21]],}
output = []
for pair in sum(order_session.values(), []):
if sum(order_session.values(), []).count(pair) > 1 and pair not in output:
output.append(pair)
print output
...
[[100, 0], [23, 2]]
Вероятно, лучший и лучший способ сделать это, но я проделаю свой путь отсюда:
seen = []
output = []
for val in order_session.values():
for vp in val:
if vp in seen:
if not vp in output:
output.append(vp)
else:
seen.append(vp)
print(output)
В основном, это то, что нужно просмотреть все значения, и если значение было замечено раньше, но не выводится раньше, оно добавляется к выходу.
Обратите внимание, что это работает с фактическими значениями пар значений - если у вас есть объекты разного типа, которые приводят к указателям, мой алгоритм может выйти из строя (я его не тестировал, поэтому я не уверен). Python повторно использует ту же ссылку на объект для "низких" целых чисел; то есть, если вы выполняете операторы a = 5
и b = 5
после друг друга, a
и b
будут указывать на один и тот же целочисленный объект. Однако, если вы установите их, скажем, 10 ^ 5, они не будут. Но я не знаю, где предел, поэтому я не уверен, относится ли это к вашему коду.
>>> from collections import Counter
>>> D = {1:[[100,0],[22,1],[23,2]],
... 10:[[100,0],[232,0],[10,2],[11,2]],
... 22:[[5,2],[23,2]]}
>>> [k for k,v in Counter(tuple(j) for i in D.values() for j in i).items() if v>1]
[(23, 2), (100, 0)]
Если вам действительно нужен список списков
>>> [list(k) for k,v in Counter(tuple(j) for i in D.values() for j in i).items() if v>1]
[[23, 2], [100, 0]]
[(100,0),(22,1),(23,2)]