动态查找列表中的值索引

时间:2013-11-18 20:40:06

标签: python list indexing

我有两个列表如下:

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中具有相同值的值的索引。这可能吗?任何提示/提示都将深受赞赏。

感谢。

5 个答案:

答案 0 :(得分:4)

有几种方法可以做到这一点。

我可以使用zipgroupby来完成。

首先:

>>> 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行的快乐媒介通常比任何一种都要好。

答案 1 :(得分:2)

使用itertools.izip_longestitertools.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']]

要获得一系列词汇,您可以这样:

>>> 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 :(得分: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之类的独立名单等等 - 这是因为这是一个坏主意。您希望将数据保存在一起,您可以(至少)轻松地迭代,并且字典和列表列表都符合条件。

答案 3 :(得分: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()

答案 4 :(得分: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