可以在字典理解期间过滤重复值吗?

Possible to filter duplicate values during dictionary comprehension?

我正在创建一个以索引为键的随机坐标字典,坐标必须是唯一的。

我知道我可以在创建字典键后返回并过滤重复项,但是是否可以确保在通过理解创建字典的过程中没有重复项?

在伪代码中我想做这样的事情:

 d = {k: (randint,randint) for k in range if (randint,randint) not in d}

但这引用了赋值前的字典 d。

明确地说,我是通过理解创建字典,而不是修改现有字典。

如评论中所述,您应该使用循环。

想耍点花样,有老办法:

>>> from random import randint, seed
>>> seen = set()
>>> {k: (x, y) for k, x, y in ((k, randint(0,5),randint(0,5)) for k in range(50)) if (x, y) not in seen and not seen.add((x, y))}
{0: (3, 4), 1: (3, 3), 2: (4, 4), 3: (1, 1), 4: (4, 3), 5: (5, 4), 6: (1, 0), 7: (3, 2), 9: (4, 5), 10: (5, 0), 12: (3, 5), 14: (5, 1), 15: (4, 0), 17: (0, 0), 22: (1, 4), 23: (1, 5), 24: (2, 3), 25: (0, 5), 26: (0, 3), 27: (5, 2), 30: (2, 2), 32: (2, 0), 33: (0, 4), 35: (0, 2), 36: (3, 0), 38: (0, 1), 41: (5, 3)}

生成器((k, randint(0,5),randint(0,5)) for k in range(50))生成50个带索引的坐标。测试元组 k, x, ,yif (x, y) not in seen,我们评估 and 的第二部分:seen.add((x, y) returns None,因此 not seen.add((x, y) 始终是 True,但会产生副作用(将元素添加到 seen)。

缺点是dict的大小取决于重复的数量。要选择元素的数量,您必须: 1. 创建一个无限生成器; 2.取前N个唯一元素。

您可以使用 iter 函数和假哨兵创建一个无限生成器((-1, -1) 永远不会产生):

>>> it = iter(lambda: (randint(0,5),randint(0,5)), (-1, -1))

现在使用 itertools 标准模块,您可以取前 10 个元素而不重复:

>>> import itertools
>>> seen = set()
>>> dict(enumerate(itertools.islice(((x,y) for x, y in it if (x, y) not in seen and not seen.add((x, y))), 10)))
{0: (5, 0), 1: (0, 0), 2: (3, 3), 3: (1, 5), 4: (4, 1), 5: (3, 4), 6: (1, 3), 7: (5, 3), 8: (0, 3), 9: (3, 1)}

但是你应该使用循环...