我有一个看起来像这样的列表理解:
cart = [ ((p,pp),(q,qq)) for ((p,pp),(q,qq))\
in itertools.product(C.items(), repeat=2)\
if p[1:] == q[:-1] ]
C
是一个字典,其键是任意整数的元组。所有的元组都具有相同的长度。最坏的情况是所有组合都应包含在新列表中。这可能经常发生。
例如,我有一个这样的字典:
C = { (0,1):'b',
(2,0):'c',
(0,0):'d' }
我希望结果是:
cart = [ (((2, 0), 'c'), ((0, 1), 'b'))
(((2, 0), 'c'), ((0, 0), 'd'))
(((0, 0), 'd'), ((0, 1), 'b'))
(((0, 0), 'd'), ((0, 0), 'd')) ]
因此,我指的是重叠,例如,元组(1,2,3,4)
具有(2,3,4,5)
重叠部分 (2,3,4)。重叠部分必须在元组的“边缘”上。我只想要长度比元组长度短一的重叠。因此(1,2,3,4)
不与 重叠(3,4,5,6)
。另请注意,当删除元组的第一个或最后一个元素时,我们最终可能会得到非不同的元组,所有这些元组都必须与所有其他元素进行比较。在我的第一个例子中没有强调最后一点。
我的代码执行时间的大部分时间都花在了这个列表理解上。我总是需要所有元素,cart
所以在使用生成器时似乎没有加速。
我的问题是:有没有更快的方法来做到这一点?
我的一个想法是,我可以尝试创建两个这样的新字典:
aa = defaultdict(list)
bb = defaultdict(list)
[aa[p[1:]].append(p) for p in C.keys()]
[bb[p[:-1]].append(p) for p in C.keys()]
并以某种方式将列表中元素的所有组合与列表中的所有组合合并aa[i]
,bb[i]
但i
我似乎也无法理解这个想法。
更新
tobias_k 和 shx2 添加的解决方案都比我的原始代码具有更好的复杂性(据我所知)。我的代码是 O(n^2),而其他两个解决方案是 O(n)。然而,对于我的问题规模和组成,所有三种解决方案似乎或多或少同时运行。我想这与函数调用相关的开销以及我正在使用的数据的性质有关。特别是不同键的数量,以及键的实际组成,似乎有很大的影响。我知道后者是因为对于完全随机的键,代码运行速度要慢得多。我接受了 tobias_k 的回答,因为他的代码最容易理解。但是,我仍然非常欢迎有关如何执行此任务的其他建议。