如何使用列表映射键值?

时间:2013-12-20 22:45:50

标签: python python-2.7

我想做以下事情:

1]将列表a中的每个元素与b进行比较并映射相似的值。

a=[1, 2, 3, 6, 4, 5, 7, 8, 9]
b=[4, 4, 5, 5, 7, 7, 9, 9, 10]

我试过以下:

c = set(a) & set(b)
>>> set([9,4,5,7])

2]我希望这些映射值的编号顺序与列表b中的编号顺序相同,例如4,5,7,9。

3]最后我想使用这些键值(4,5,7,9)并从列表a生成相应的值,例如:

4 (1,2)
5 (3,6)
7 (4,5)
9 (7,8)

任何建议都会非常感激?

3 个答案:

答案 0 :(得分:2)

要解决您的问题3,您需要将每个列表与对方集进行比较。这将自动解决您的#2。

还有其他方法可以解决#2,比如使用OrderedSet(比如recipe中链接到的collections docs),但由于它们无法解决#3,所以没有必要进入这一点。


如果a值非常大,您可能希望构建索引结构 - 将值映射到索引集合的字典 - 以使其更快。像这样:

rev_a = collections.defaultdict(list)
for index, value in enumerate(a):
    rev_a[value].append(index)

然后查找部分变得更容易,更快:

for b_value in b:
    a_indices = rev_a[b_value]
    if a_indices:
        a_str = ','.join(map(str, a_indices))
        print('{} is associated with ({})'.format(b_value, a_str))

或者,如果你想创建某种结构而不是即时打印:

results = [(b_value, rev_a[b_value]) for b_value in b]
results = OrderedDict((b_value, rev_a[b_value]) for b_value in b)
# etc.

这实际上并没有产生你要求的输出,但是......我不确定你要求的输出应该是什么来的。除非您从其他列表中获取匹配的索引,然后在第一个列表中查找它们?这至少是奇怪的。无论如何,像这样的索引结构应该使得实现你提出的任何规则变得微不足道,即使是更奇怪的规则,只要你能够解释它。

例如,将a_str行替换为:

a_str = ','.join(str(a[a_index] for index in a_indices))

...你得到了你想要的输出。

答案 1 :(得分:2)

现在您已经更新了问题,我发现您真正想要的只是价值键的映射:

a = [1, 2, 3, 6, 4, 5, 7, 8, 9]
b = [4, 4, 5, 5, 7, 7, 9, 9, 10]

r = dict([(x, []) for x in b])

for k, v in zip(b, a):
    r[k] += [v,]

以下是如何使用结果:

>>> for k, v in r.items():
...     print k, v
... 
9 [7, 8]
10 [9,]
4 [1, 2]
5 [3, 6]
7 [4, 5]
>>> 
>>> print r[4]
[1, 2]

这是一个优化版本,可以更快地运行,内存使用量更少:

from itertools import izip
from collections import defaultdict
r = defaultdict(list)

for k, v in izip(b, a):
    r[k] += [v]

答案 2 :(得分:0)

您可以使用list comprehension

>>> a=[1, 2, 3, 6, 4, 5, 7, 8, 9]
>>> b=[4, 4, 5, 5, 7, 7, 9, 9, 10]
>>> [x for x in a if x in b]
[4, 5, 7, 9]