2013-11-18 2 views
0

У меня возникают два списка следующим образом:Нахождение индекса значений в списке динамически

list_1 
['A-1','A-1','A-1','A-2','A-2','A-3'] 

list_2 
['iPad','iPod','iPhone','Windows','X-box','Kindle'] 

Я хотел бы разделить list_2 на основе значений индекса в list_1. Например,

list_a1 
['iPad','iPod','iPhone'] 

list_a2 
['Windows','X-box'] 

list_a3 
['Kindle'] 

Я знаю метод индекса, но ему нужно значение, которое должно быть согласовано с ним. В этом случае я хотел бы динамически находить индексы значений в list_1 с тем же значением. Это возможно? Любые советы/подсказки будут глубоко оценены.

Спасибо.

+0

Обязательно ли сортировать 'list_1' (чтобы все вхождения каждого значения индекса отображались в строке)? –

+0

Да ... list_1 значения упорядочены ... все сначала A-1, затем A-2 и т. Д. ... и значения в списке_2 следуют соответствующему порядку в списке_1 – visakh

+0

Спасибо за ответы ... один из несколько моментов, когда я хочу выбрать оба ответа ... :-) – visakh

ответ

4

Существует несколько способов сделать это.

Я бы сделал это, используя zip и groupby.

Первое:

>>> list(zip(list_1, list_2)) 
[('A-1', 'iPad'), 
('A-1', 'iPod'), 
('A-1', 'iPhone'), 
('A-2', 'Windows'), 
('A-2', 'X-box'), 
('A-3', 'Kindle')] 

Сейчас:

>>> import itertools, operator 
>>> [(key, list(group)) for key, group in 
... itertools.groupby(zip(list_1, list_2), operator.itemgetter(0))] 
[('A-1', [('A-1', 'iPad'), ('A-1', 'iPod'), ('A-1', 'iPhone')]), 
('A-2', [('A-2', 'Windows'), ('A-2', 'X-box')]), 
('A-3', [('A-3', 'Kindle')])] 

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

>>> [list(zip(*group))[1] for key, group in 
... itertools.groupby(zip(list_1, list_2), operator.itemgetter(0))] 
[('iPad', 'iPod', 'iPhone'), ('Windows', 'X-box'), ('Kindle',)] 

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

>>> ziplists = zip(list_1, list_2) 
>>> pairs = itertools.groupby(ziplists, operator.itemgetter(0)) 
>>> groups = (group for key, group in pairs) 
>>> values = (zip(*group)[1] for group in groups) 
>>> [list(value) for value in values] 

... но счастливая среда, возможно, 2 или 3 линии, как правило, лучше, чем любая крайность.

2

Использование itertools.izip_longest и itertools.groupby:

>>> from itertools import groupby, izip_longest 
>>> inds = [next(g)[0] for k, g in groupby(enumerate(list_1), key=lambda x:x[1])] 

предметы первой группы list_1 и найти начальный индекс каждой группы:

>>> inds 
[0, 3, 5] 

Теперь использовать нарезку и izip_longest, как нам нужно пар list_2[0:3], list_2[3:5], list_2[5:]:

>>> [list_2[x:y] for x, y in izip_longest(inds, inds[1:])] 
[['iPad', 'iPod', 'iPhone'], ['Windows', 'X-box'], ['Kindle']] 

Чтобы получить список dicts вы можете что-то вроде:

>>> inds = [next(g) for k, g in groupby(enumerate(list_1), key=lambda x:x[1])] 
>>> {k: list_2[ind1: ind2[0]] for (ind1, k), ind2 in 
            zip_longest(inds, inds[1:], fillvalue=[None])} 
{'A-1': ['iPad', 'iPod', 'iPhone'], 'A-3': ['Kindle'], 'A-2': ['Windows', 'X-box']} 
2

Обычно я один бросаясь к решению groupby; ^), но здесь я пойду другим путем и вручную вставить в OrderedDict :

list_1 = ['A-1','A-1','A-1','A-2','A-2','A-3'] 
list_2 = ['iPad','iPod','iPhone','Windows','X-box','Kindle'] 

from collections import OrderedDict 

d = OrderedDict() 
for code, product in zip(list_1, list_2): 
    d.setdefault(code, []).append(product) 

производит d похожий

>>> d 
OrderedDict([('A-1', ['iPad', 'iPod', 'iPhone']), 
      ('A-2', ['Windows', 'X-box']), ('A-3', ['Kindle'])]) 

с легким доступом:

>>> d["A-2"] 
['Windows', 'X-box'] 

и мы можем получить список-из-списков в list_1 порядке с помощью .values():

>>> d.values() 
[['iPad', 'iPod', 'iPhone'], ['Windows', 'X-box'], ['Kindle']] 

Если вы заметили, что никто не говорит вам, как сделать кучу независимых списков с такие имена, как list_a1 и т. д., потому что это плохая идея. Вы хотите, чтобы данные были объединены во что-то, что вы можете (как минимум) легко перебирать, и оба словаря и список списков квалифицируются.

+0

Отличный пункт в последнем абзаце. Все остальные просто предполагали, что вместо объяснения этого. – abarnert

2

Возможно, что-то вроде этого?

#!/usr/local/cpython-3.3/bin/python 

import pprint 
import collections 

def main(): 
    list_1 = ['A-1','A-1','A-1','A-2','A-2','A-3'] 
    list_2 = ['iPad','iPod','iPhone','Windows','X-box','Kindle'] 

    result = collections.defaultdict(list) 
    for list_1_element, list_2_element in zip(list_1, list_2): 
     result[list_1_element].append(list_2_element) 

    pprint.pprint(result) 


main() 
0

Вы можете сделать это, если хотите простой код, это некрасиво, но выполняет свою работу.

list_1 = ['A-1','A-1','A-1','A-2','A-2','A-3'] 
list_2 = ['iPad','iPod','iPhone','Windows','X-box','Kindle'] 
list_1a = [] 
list_1b = [] 
list_1c = [] 
place = 0 
for i in list_1[::1]: 
    if list_1[place] == 'A-1': 
     list_1a.append(list_2[place]) 
    elif list_1[place] == 'A-2': 
     list_1b.append(list_2[place]) 
    else: 
     list_1c.append(list_2[place]) 
    place += 1 
Смежные вопросы