2013-11-18 3 views
1

Я знаю, что это, наверное, глупый вопрос, и я извиняюсь за это, но я очень новичок в python и пытался решить это уже давно, без успеха. У меня есть список кортежей, похожий на один ниже:Адаптация вложенных кортежей

data = [('ralph picked', ['nose', '4', 'apple', '30', 'winner', '3']), 
('aaron popped', ['soda', '1', 'popcorn', '6', 'pill', '4', 'question', '29'])] 

Я хотел бы отсортировать вложенный список в убывающем других:

data = [('ralph picked', ['apple', '30', 'nose', '4', 'winner', '3']), 
('aaron popped', ['question', '29', 'popcorn', '6', 'pill', '4', 'soda', '1'])] 

Я попытался с помощью простого

sorted(data) 

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

+1

Я бы не назвал его сортировкой. Что вы делаете: ** Организация ** –

+1

Почему '4' появляется один раз в первой строке первого примера, но дважды в первой строке второго примера? Никакая сортировка не превратит список шести элементов в семь элементов. – Kevin

+0

@ Кевин, спасибо, Кевин, это была опечатка, я ее исправил. – user2962024

ответ

1

Рассмотрим только внутренний список. Первая проблема заключается в том, что кажется, что вы хотите держать слово, пары чисел вместе. Мы можем использовать zip, чтобы объединить их, помня, что seq[::2] дает нам каждый второй элемент, начиная с 0-го, и seq[1::2] дает нам каждый второй, начиная с первого:

>>> s = ['nose', '4', 'apple', '30', 'winner', '3'] 
>>> zip(s[::2], s[1::2]) 
<zip object at 0xb5e996ac> 
>>> list(zip(s[::2], s[1::2])) 
[('nose', '4'), ('apple', '30'), ('winner', '3')] 

Теперь, когда вы обнаружили, если вы звоните sorted в последовательности, он сортирует сначала по первому элементу, а затем второму, чтобы разорвать связи и т. Д., Идя настолько глубоко, насколько это необходимо. Так что, если мы называем sorted на это:

>>> sorted(zip(s[::2], s[1::2])) 
[('apple', '30'), ('nose', '4'), ('winner', '3')] 

Ну, это выглядит, как это работает, но только потому, что трематоды apple-nose-winner в алфавитном порядке. Действительно, мы хотим сортировать по второму термину. sorted принимает key параметр:

>>> sorted(zip(s[::2], s[1::2]), key=lambda x: x[1]) 
[('winner', '3'), ('apple', '30'), ('nose', '4')] 

Это не сработало, потому что это сортирует число строк в лексикографическом (словарь-стиль, поэтому «30» предшествует «4»). Мы можем сказать, это мы хотим использовать численное значение, хотя:

>>> sorted(zip(s[::2], s[1::2]), key=lambda x: int(x[1])) 
[('winner', '3'), ('nose', '4'), ('apple', '30')] 

Почти там - мы хотим, чтобы эта обратная:

>>> sorted(zip(s[::2], s[1::2]), key=lambda x: int(x[1]), reverse=True) 
[('apple', '30'), ('nose', '4'), ('winner', '3')] 

И это почти сразу, но нам нужно, чтобы выровнять его. Мы можем использовать либо вложенный список понимание:

>>> s2 = sorted(zip(s[::2], s[1::2]), key=lambda x: int(x[1]), reverse=True) 
>>> [value for pair in s2 for value in pair] 
['apple', '30', 'nose', '4', 'winner', '3'] 

или использовать itertools.chain:

>>> from itertools import chain 
>>> list(chain.from_iterable(s2)) 
['apple', '30', 'nose', '4', 'winner', '3'] 

И я думаю, что это, где мы хотели пойти.

+0

Вау, это было очень ясно и дидактично, спасибо. Извините, однако, потому что я не знаю, как адаптировать ваш ответ к существующему списку. Я, вероятно, что-то пропустил, но мне действительно нужно сохранить внутренний список внутри большего.Любые советы о том, как сделать эту работу в моем существующем списке, с вложенной частью? – user2962024

+0

Это довольно просто. Вы знаете, как перебирать список и изменять элемент по индексу? – DSM

+0

Мне удалось создать цикл, но теперь я получаю сообщение об ошибке в строке 'sorted (zip (s [:: 2], s [1 :: 2]), key = lambda x: int (x [ 1]), reverse = True) ', он говорит, что аргумент' int() должен быть строкой или числом, а не 'tuple''. Я попытался заменить 'int', но безуспешно. Любые идеи о том, как это может быть? Я весьма признателен. – user2962024

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