Python - 为什么映射两个列表时字典会缩减?

1 投票
5 回答
918 浏览
提问于 2025-04-19 21:24

我有两个很大的列表,每个列表都有2574个项目,长度是一样的。我想把这些项目放进一个字典里,因为我想知道哪些值和它们的键不一样。每个键只对应一个值。不过,当我把它们放进字典时,结果却变成了一个只有76个项目的短字典。

这是一个测试:

Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> list1 = [1, 1, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 10]
>>> list2 = [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10]
>>> 
>>> listdict = dict(zip(list1, list2))
>>> print len(list1)
14
>>> print len(list2)
14
>>> print len(listdict)
8
>>> print listdict
{1: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 9, 10: 10}

那么,为什么使用 dict(zip()) 会把那些可以一一对应的1和8给去掉,而其他的却保留呢?其实,我的两个列表长度是一样的,我需要知道每个位置的项目是否不同。比较的时候,两个列表中的位置必须一一对应。比如说,list1[0] 要和 list2[0] 比较,而不能随便比较其他位置。当我得到字典的时候,我以为这样做就能成功:

for k,v in listdict:
if k != v:
print k, '\t', v

但它们并没有正确匹配...

5 个回答

0

为了保持元素的长度和顺序,就像在列表中那样,可以使用

OrderedDict(zip(list1,list2))
1

字典(dict)是用来把每个键(key)和一个值(value)对应起来的。如果你把同一个键设置成不同的值(或者说是相同的值),后面的值会覆盖前面的值。举个例子:

>>> d = {}
>>> d[1] = 23
>>> d
{1: 23}
>>> d[1] = 69105
>>> d
{1: 69105}

如果你想要每个键能存多个值,那你需要的是“多重字典”(multidict),而不是普通的字典。Python里没有直接提供这种功能,但用defaultdict可以很简单地模拟出来:

>>> import collections
>>> d = collections.defaultdict(set)
>>> d[1].add(23)
>>> d
{1: {23}}
>>> d[1].add(69105)
>>> d
{1: {69105, 23}}

所以,如果你想写一个函数,从一对对的值中创建一个多重字典,其实很容易:

def make_multidict(pairs):
    d = collections.defaultdict(set)
    for k, v in pairs:
        d[k].add(v)
    return d
1

为了同时保留list1中的每个项目和它的位置,可以使用enumerate这个工具。

>>> listdict = dict(zip(enumerate(list1), list2))
>>> listdict
{(0, 1): 1, (10, 8): 8, (6, 7): 7, (5, 6): 6, (7, 8): 8, (9, 8): 8, (13, 10): 10, (4, 5): 5, (8, 8): 8, (2, 3): 3, (11, 8): 8, (3, 4): 4, (1, 1): 2, (12, 8): 9}

listdict中,每个键都是一个元组,里面包含了list1中的一个索引和那个位置上的项目。

2

字典的键必须是唯一的。只有最后一个1的键被保留,最后一个8的键也是如此。

当你多次指定一个键时,只有一个(也就是最后处理的那个)有效

>>> {1: 1, 1: 2}
{1: 2}

如果你想找出哪些值和它们的键不一样,别用字典,直接收集那些不一样的键值对:

different = [pair for pair in zip(list1, list2) if pair[0] != pair[1]]

你可以用enumerate()给这个加上索引:

different = [(i, pair) for i, pair in enumerate(zip(list1, list2)) if pair[0] != pair[1]]

示例:

>>> list1 = [1, 1, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 10]
>>> list2 = [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10]
>>> [pair for pair in zip(list1, list2) if pair[0] != pair[1]]
[(1, 2), (8, 9)]
>>> [(i, pair) for i, pair in enumerate(zip(list1, list2)) if pair[0] != pair[1]]
[(1, (1, 2)), (12, (8, 9))]
3

正如其他回答所说,dict(字典)里的键必须是唯一的,也就是说不能有重复的键。

听起来你可能更想要的是一个包含元组的列表,而不是字典。所以你可以试试这个方法:listtup = list(zip(list1, list2)),而不是之前的listdict = dict(zip(list1, list2))

>>> list1 = [1, 1, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 10]
>>> list2 = [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 9, 10]
>>> listtup = list(zip(list1, list2))
>>> listtup
[(1, 1), (1, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (8, 8), (8, 8), (8, 8), (8, 8), (8, 9), (10, 10)]

撰写回答