7

我想知道 Python 中是否已经为我稍后描述的目标编写了一个函数。如果没有,最简单的实现方法是什么。附上我的代码。

假设我的范围从 1 到 999999999。给定这样的数字列表:

[9, 44, 99]

它会回来

[(1,9), (10,44), (45,99), (100, 999999999)]

如果作为限制的数字包含在输入数字中,它也应该处理它。说输入是

[1, 9, 44, 999999999]

回报应该是:

[(1,9), (10,44), (45, 999999999)]

我可以编写一个 for 循环与一些条件语句进行比较,但想知道是否有更“智能的方式”。

一些可能有用的数据按摩:

points = [1, 9, 44, 99]
points = sorted(list(set(points + [1, 999999999])))

更新信息:alecxe 的最终学分,感谢您鼓舞人心的列表理解解决方案

l = sorted(list(set(points + [1, 999999999])))
[(l[i] + int(i != 0), l[i + 1]) for i in xrange(len(l) - 1)]

您可以将所有这些放在一行中,但我认为这是不必要的。

4

4 回答 4

19

熊猫.cut()

例子

[1,2,3,4,5,6,7,8,9,10] ---> [A,A,B,B,C,C,D,D,E,E]

回复:

x  <- seq(1,10,1)
cut(x, breaks = seq(0,10,2), labels = c('A','B','C','D','E'))

Python:

import pandas
x = range(1, 11, 1)
pandas.cut(x, bins=range(0, 12, 2), labels=['A','B','C','D','E'])
于 2016-11-08T16:51:40.493 回答
1
def myCut(low, high, points):
    answer = []
    curr = low
    for point in points:
        answer.append((curr, point))
        curr = point + 1
    answer.append((curr, high))
    return answer

>>> low = 1
>>> high = 999999999
>>> points = [9, 44, 109]
>>> myCut(low, high, points)
[(1, 9), (10, 44), (45, 109), (110, 999999999)]

受此答案和随后的讨论的启发,这里有一个更少行的解决方案,带有itertools. 这使用itertools.chainand itertools.izip(在 python2.7 中;zip在 python3.x 中)来减少由添加列表、排序和设置引起的时间和空间复杂性。请注意,该解决方案假定输入列表已经排序,否则将产生错误的结果

cuts = [(i+1, j) for i,j in itertools.izip(itertools.chain([0], myList), itertools.chain(myList, [999999999]))]

>>> import itertools
>>> myList = [9, 44, 99]
>>> [(i+1, j) for i,j in itertools.izip(itertools.chain([0], myList), itertools.
chain(myList, [999999999]))]
[(1, 9), (10, 44), (45, 99), (100, 999999999)]
于 2013-08-30T18:06:15.050 回答
1

不确定这种方法是最好的方法:

>>> l = [1, 9, 44, 999999999]
>>> [(l[i] + int(i != 0), l[i + 1]) for i in xrange(len(l) - 1)]
[(1, 9), (10, 44), (45, 999999999)]

如果您使用的是 python 3,请替换xrangerange.

请注意,要使您的第一个示例正常工作,您需要预先添加和附加边界:

>>> l = [9, 44, 109]
>>> low, high = 1, 999999999
>>> l = [low] + l + [high]
>>> [(l[i] + int(i != 0), l[i + 1]) for i in xrange(len(l) - 1)]
[(1, 9), (10, 44), (45, 109), (110, 999999999)]
于 2013-08-30T18:06:22.637 回答
0

将答案中的代码与 timeit 进行比较,看起来 inspectorG4dget 的解决方案表现得更好(尤其是使用 Python 3),即使我没有在列表理解解决方案中添加低值和高值:

ls = [9, 44, 109, 200, 567, 894, 6879, 29823]

def f1(low, high, points):
    answer = []
    curr = low
    for point in points:
        answer.append((curr, point))
        curr = point + 1
    answer.append((curr, high))
    return answer

def f2(low, high, l):
    a = [(l[i] + int(i != 0), l[i + 1]) for i in range(len(l) - 1)]
    return a

if __name__ == '__main__':
    import timeit

    print(timeit.timeit("f1(1, 99999999, ls)", setup="from __main__ import f1, ls"))
    print(timeit.timeit("f2(1, 99999999, ls)", setup="from __main__ import f2, ls"))

结果(我上网本上的py3):

3.2064807919996383
8.850830605999363
于 2013-08-30T20:33:08.877 回答