我有一个很长的列表(大约1000万个元素),并且具有重复值的元素是成对的。我想从列表中提取对列表,例如
R = [1,3,1,6,9,6,1,2,3,0]
将吐出对的列表
P = [[e1,e3],[e1,e7],[e3,e7],[e4,e6],[e2,e9]]
为长列表实现此目的的有效算法是什么?
答案 0 :(得分:1)
根据值将索引组合在一起,然后使用combinations
迭代索引对。
from collections import defaultdict
from itertools import combinations
R = [1,3,1,6,9,6,1,2,3,0]
d = defaultdict(list)
for idx,item in enumerate(R,1):
d[item].append(idx)
result = []
for indices in d.itervalues():
result.extend(combinations(indices, 2))
print result
结果:
[(1, 3), (1, 7), (3, 7), (2, 9), (4, 6)]
填充defaultdict平均需要O(len(R))时间。查找组合是O(N!)时间,其中N是最大组中的索引数。
答案 1 :(得分:0)
我的方法是对列表进行传递以找到具有相同值的元素并将它们存储到新列表中,然后找到不止一次出现的元素并收集组合:
In [18]: from collections import defaultdict
In [19]: d = defaultdict(list)
In [20]: for i, e in enumerate(R, 1):
....: d[e].append(i)
....:
In [21]: from itertools import combinations
In [22]: from itertools import chain
In [23]: list(chain(*[list(combinations(v,2)) for v in d.values() if len(v) > 1]))
Out[23]: [(1, 3), (1, 7), (3, 7), (2, 9), (4, 6)]
答案 2 :(得分:0)
我的简单解决方案:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="">
<meta name="description" content="Fraction Learning app for Children">
<title>Fractions Fun</title>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<br>
<input type="number" id="num" />/
<input type="number" id="den" />
<br>
<button id="draw">
DRAW
</button>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var pi = Math.PI;
document.getElementById("draw").addEventListener("click", function() {
var num = document.getElementById("num").value;
var den = document.getElementById("den").value;
var rad = 2 / den * num * pi;
var cx = 250;
var cy = 250;
ctx.clearRect(0, 0, 500, 500);
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.arc(cx, cy, 220, 1.5 * pi, 1.5 * pi + rad);
ctx.lineTo(cx, cy);
ctx.fillStyle = "#FF0000";
ctx.fill();
ctx.closePath();
ctx.stroke();
});
</script>
</body>
由于我们无法看到您的输入,如果有许多组合,您可能会遇到问题。有一件事要尝试pypy,这有时会让我(免费)加速。
答案 3 :(得分:0)
除非我以错误的方式理解,否则最简单和最佳的方法是使用已经遇到的值的字典。
elem_dict = {}
output = []
for i, elem in zip (range (length(R))),R):
if elem_dict.has_key (elem):
output += [[duplicate, i] for duplicate in elem_dict[elem]]
else
elem_dict[elem] = set ()
elem_dict[elem].add (i)
print output #[[0, 2], [3, 5], [0, 6], [2, 6], [1, 8]]
在平均情况下应该是O(n log(n)),如果我没有弄错,除非你有很多类似的值,在这种情况下你的输出仍然是O(n ^ 2)。