我有一个范围列表,例如0-100。 我需要尽可能快地获得仅出现一次的唯一值。
例如范围:
0 - 10
5 - 20
30 - 40
0 - 10(+11)是唯一的,这些数字都没有出现在
之前5 - 10不是唯一的,所以不要计算它们。
11 - 20(+10)是唯一的,30 - 40(+11)也是
这样它返回32。
有什么建议吗?
答案 0 :(得分:1)
>>> a = range(11)
>>> b = range(5, 21)
>>> c = range(30, 41)
>>> set(i for i in a + b + c)
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40])
>>> len(_)
32
或更好:
>>> from itertools import chain
>>> a = xrange(11)
>>> b = xrange(5, 21)
>>> c = xrange(30, 41)
>>> set(chain(a, b, c))
在Python 3中:
>>> from itertools import chain
>>> a = range(11)
>>> b = range(5, 21)
>>> c = range(30, 41)
>>> set(chain(a, b, c))
希望它有所帮助!
答案 1 :(得分:1)
在您的示例中,范围按范围的下限按升序排序。我会假设这个解决方案始终如此。
基本上,我们的想法是迭代范围,每次都为计数变量添加唯一值。
要确定唯一值的起始位置,请比较上一个范围结束的位置与新范围开始的位置。
如果新范围的下限小于旧上限,即I.e。 0-10然后是5-20,根据您的示例,唯一值将从前一个上限+ 1开始(即,上限为10,唯一从11开始)。如果新的上限小于旧的上限,则没有要添加的新值(即0-10,然后是2-7)。
最后,如果新的下限大于旧上限(即5-20然后30-40),则所有新值都是唯一的。
伪代码:
var count = 0, lowerBound = 0, upperBound = 0;
foreach range in ranges:
if range.lowerBound <= upperBound:
if range.upperBound < upperBound:
continue;
else:
lowerBound = upperBound + 1;
else:
lowerBound = range.lowerBound;
upperBound = range.upperBound;
count += upperBound - lowerBound + 1;