2012-05-28 3 views
0

У меня есть списоксписок Создание списка Oneliner -python

l=[(1,2),(1,6),(3,4),(3,6),(1,4),(4,3)] 

Я хочу, чтобы вернуться в список, содержащий списки под первым номером в каждом наборе. Что-то вроде этого:

[[2,4,6],[4,6],[3]] 

Чтобы сделать программу, которая перебирает на списке и писать целую функцию, которая делает это легко. Я хочу найти способ oneliner - python сделать это. Любые идеи?

+0

Не уверен, что я понимаю, как ваш ввод относится к вашему выходу, не могли бы вы объяснить немного больше? – Levon

+1

это еще не имеет значения – wim

ответ

10
>>> from itertools import groupby 
>>> from operator import itemgetter 
>>> L = [(1,2), (1,6), (3,4), (3,6), (1,4), (4,3)] 
>>> [[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))] 
[[2, 4, 6], [4, 6], [3]] 

Объяснение

Это работает с использованием itertools.groupby. groupby находит последовательных групп в итерабельном, возвращая итератор через ключ, группы пар.

Аргумент, присвоенный groupby, является ключевой функцией itemgetter(0), которая вызывается для каждого кортежа, возвращая первый элемент в качестве ключа к groupby.

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

>>> sorted(L) 
[(1, 2), (1, 4), (1, 6), (3, 4), (3, 6), (4, 3)] 

Существует отсортированный список, в котором вы можете четко видеть группы, которые будут созданы, если вы оглянетесь на конечный результат. Теперь вы можете использовать groupby, чтобы показать ключи, группы.

[(1, <itertools._grouper object at 0x02BB7ED0>), (3, <itertools._grouper object at 0x02BB7CF0>), (4, <itertools._grouper object at 0x02BB7E30>)] 

Здесь представлены отсортированные элементы, сгруппированные по первому номеру. groupby возвращает группу для каждого ключа как итератора, это замечательно и очень эффективно, но для этого примера мы просто преобразуем его в list, чтобы убедиться, что он работает правильно.

>>> [(k, list(v)) for k,v in groupby(sorted(L), itemgetter(0))] 
[(1, [(1, 2), (1, 4), (1, 6)]), (3, [(3, 4), (3, 6)]), (4, [(4, 3)])] 

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

[[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))] 
+0

+1 для отличного понимания .. как вы получили это из оригинального вопроса! – Levon

+2

хорошие психические способности ... я до сих пор не понимаю! – wim

+0

@ Levon Спасибо, я просто сделал вопрос вроде этого, но я не уверен, почему это трудно понять ... – jamylak

2
l = [(1, 2), (1, 6), (3, 4), (3, 6), (1, 4), (4, 3)] 

d = {} 
for (k, v) in l: 
    d.setdefault(k, []).append(v) 

print d.values() 

Я знаю, что это не один лайнер, но, возможно, легче читать, чем один лайнер.

+0

+1 Это, вероятно, лучший способ сделать это, если вопрос не просил одного лайнера. Я бы предложил изменить '(k, v)' на 'k, v' – jamylak

+0

Прохладный, я не знал, что вы можете это сделать. Благодарю. –

Смежные вопросы