Об’єднання пар елементів списку


82

Я знаю, що список можна об’єднати, щоб зробити один довгий рядок, як у:

x = ['a', 'b', 'c', 'd']
print ''.join(x)

Очевидно, це дасть результат:

'abcd'

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

['ab', 'cd']

Чи є якийсь простий спосіб зробити це? Ймовірно, слід також згадати, що довжини рядків у списку будуть непередбачуваними, як і кількість рядків у списку, хоча кількість рядків завжди буде парною. Тож оригінальний список міг би так само бути:

['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'] 

"Мені, мабуть, слід також згадати, що довжини рядків у списку будуть непередбачуваними" - То чи довжина має значення? Тобто, ви просто хочете приєднатись до кожної пари елементів списку, або ви насправді хочете переглянути вміст і приєднатися до тих пір, поки отриманий елемент залишається нижче якоїсь спеціальної межі довжини?
тикати

просто приєднайтеся до кожної пари, я просто подумав, що незнання кількості пар може бути проблемою
Джон

Відповіді:


76

Ви можете використовувати нотацію фрагментів із кроками:

>>> x = "abcdefghijklm"
>>> x[0::2] #0. 2. 4...
'acegikm'
>>> x[1::2] #1. 3. 5 ..
'bdfhjl'
>>> [i+j for i,j in zip(x[::2], x[1::2])] # zip makes (0,1),(2,3) ...
['ab', 'cd', 'ef', 'gh', 'ij', 'kl']

Така ж логіка застосовується і до списків. Довжина рядка не має значення, оскільки ви просто додаєте два рядки разом.


1
Немає сумнівів, що відповідь Кевпі набагато краща. У цьому x[:::2]створюється об’єкт, x[1::2]створюється інший об’єкт, ці створення, ймовірно, базується на обчисленні індексів під капотом, і перед тим, як отримати послідовні пари елементів, необхідний виклик функції з цими двома об’єктами, переданими як аргументи. які повинні бути об'єднані. Хоча у відповіді kevpie є просто створення одного ітератора, а потім ітерація переходить від елемента до елемента недоторканого списку, не дбаючи про індекси, і це набагато пітонічніше.
eyquem

@eyquem, використовуючи itertools.isliceзамість [], усуває проміжні об'єкти. Але оскільки обидві відповіді працюють за однакових умов і повертаються однаково, вони обидві мають рацію. І zip(i[::2], i[1::2])здається мені таким солодким, так, чому б і ні? :)
utdemir

Це працює лише на послідовності , тоді як відповідь @ kevpie є більш загальною і працює на будь-яку ітерацію .
Кос,

37

Використовуйте ітератор.

Розуміння списку:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> [c+next(si, '') for c in si]
['abcde', 'fghijklmn', 'opqr']
  • Дуже ефективний для використання пам'яті.
  • Рівно один обхід с

Вираз генератора:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> pair_iter = (c+next(si, '') for c in si)
>>> pair_iter # can be used in a for loop
<generator object at 0x4ccaa8>
>>> list(pair_iter) 
['abcde', 'fghijklmn', 'opqr']
  • використовувати як ітератор

Використовуючи карту, str .__ add__, iter

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> map(str.__add__, si, si)
['abcde', 'fghijklmn', 'opqr']

наступний (ітератор [, за замовчуванням]) доступний, починаючи з Python 2.6


2
Безумовно, найкраща відповідь. Дивіться мій коментар до відповіді utdemir.
eyquem

4

просто щоб бути пітонічним :-)

>>> x = ['a1sd','23df','aaa','ccc','rrrr', 'ssss', 'e', '']
>>> [x[i] + x[i+1] for i in range(0,len(x),2)]
['a1sd23df', 'aaaccc', 'rrrrssss', 'e']

якщо ви хочете насторожитися, якщо довжина списку непарна, ви можете спробувати:

[x[i] + x[i+1] if not len(x) %2 else 'odd index' for i in range(0,len(x),2)]

Удачі


2

Без складання тимчасових списків:

>>> import itertools
>>> s = 'abcdefgh'
>>> si = iter(s)
>>> [''.join(each) for each in itertools.izip(si, si)]
['ab', 'cd', 'ef', 'gh']

або:

>>> import itertools
>>> s = 'abcdefgh'
>>> si = iter(s)
>>> map(''.join, itertools.izip(si, si))
['ab', 'cd', 'ef', 'gh']

Приємно, але, враховуючи мій код, я все одно починаю з оригінального списку, я думаю, що не вибрав utdmr .... дякую, хоча
Джон

1
>>> lst =  ['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'] 
>>> print [lst[2*i]+lst[2*i+1] for i in range(len(lst)/2)]
['abcde', 'fghijklmn', 'opqr']

1

Ну, я б зробив це таким чином, оскільки мені погано до Реґа.

КОД

t = '1. eat, food\n\
7am\n\
2. brush, teeth\n\
8am\n\
3. crack, eggs\n\
1pm'.splitlines()

print [i+j for i,j in zip(t[::2],t[1::2])]

вихід:

['1. eat, food   7am', '2. brush, teeth   8am', '3. crack, eggs   1pm']  

Сподіваюся, це допомагає :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.