字典理解附加可变长度列表

dictionary comprehension to append variable length lists

我正在寻找创建列表字典的 pythonic 方法,您可以在其中将值附加到一系列键的列表中。因此,一个字典 n 存储 1000 以内值的数字总和,数字总和为键,例如:

n[25] = [799, 889, 898, 979, 988, 997]

使用基本的列表理解不起作用,因为它会覆盖较小的值,并且每个键只允许一个最大的值,

n = {sumdigits(i): i for i in range(1000)}

我在下面有一个两行的工作版本,但我很好奇是否有一个简洁的单行解决方案来创建可变长度列表的字典。

def sumdigits(x):
  return sum(int(i) for i in str(x))

n = defaultdict(list)
for i in range(1000):  
  n[sumdigits(i)].append(i)

如果你真的想要一个在线的解决方案,你可以做以下组合列表和字典理解:

dct = {sumdigits(i): [j for j in range(1000) if sumdigits(i)==sumdigits(j)] for i in range(1000)}

就是说,我不认为它比您自己建议的简单 for 循环更具 Python 风格,我认为出于性能原因您也应该坚持使用它。

你已经拥有的东西非常pythonic。它绝对没有任何问题,关键是它很清楚发生了什么。

如果你真的想要一个单行解决方案,我认为你需要 2 个循环。 n 值的一个循环,可以是 1 到 27 (sumdigits(999)) 之间的任何值。然后另一个循环遍历 1-1000 范围内的项目。

这是它的样子,但从时间复杂度的角度来看,它的效率非常低。你所拥有的时间复杂度为 O(n),这很好。但是在理解中做到这一点很复杂 O(n^sumdigits(n-1))。因为对于每个键,您都必须遍历 1-1000 的整个范围,但其中大部分都被丢弃了。

{n: [i for i in range(1000) if sumdigits(i) == n] for n in range(sumdigits(999) + 1)}

这也有可能是一行(因为您不计算 2 行解决方案中的 defaultdict 初始化)。优点是它比其他解决方案快得多。

n = defaultdict(list)
{n[sum(int(d) for d in str(nb))].append(nb) for nb in range(1000)}

或者真的在一行中(使用 walrus operator python3.8 +)

{n := collections.defaultdict(list)[sum(int(i) for i in str(x))].append(x) for x in range(NB)}