代码之家  ›  专栏  ›  技术社区  ›  miku

具有重复连续数字的范围

  •  8
  • miku  · 技术社区  · 6 年前

    我想创建一个数字范围(例如(1,5)),其中包含一些重复(例如4):

    [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
    

    一种方法是写:

    list(itertools.chain(*([x] * 4 for x in range(1, 5))))
    

    或类似:

    list(itertools.chain(*(itertools.repeat(x, 4) for x in range(1, 5))))
    

    然而,有一个平坦的步骤,这是可以避免的。

    有没有更像蟒蛇或更紧凑的版本来生成这样的序列?

    7 回复  |  直到 6 年前
        1
  •  9
  •   Mihai Alexandru-Ionut    6 年前

    你可以用一个 列表理解 反而。

    l = [i for i in range(1, 5) for _ in range(4)]
    

    产量

    [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
    
        2
  •  7
  •   jpp    6 年前

    你的解决方案没有问题。但你可以用 chain.from_iterable 以避免拆包步骤。

    否则,如果你愿意使用第三方库,我唯一的建议就是使用numpy。

    from itertools import chain, repeat
    import numpy as np
    
    # list solution
    res = list(chain.from_iterable(repeat(i, 4) for i in range(1, 5)))
    
    # NumPy solution
    arr = np.repeat(np.arange(1, 5), 4)
    
        3
  •  4
  •   Mohamed Thasin ah    6 年前

    试试这个,

    range(1,5)*4 # if you don't consider order
    sorted(range(1,5)*4) # for ordered seq
    

    性能更新 .

    Mihai Alexandru Ionut回答:

    %timeit [i for i in range(1, 5) for _ in range(4)]
    
    1000000 loops, best of 3: 1.91 µs per loop
    

    JPP回答:

    %timeit list(chain.from_iterable(repeat(i, 4) for i in range(1, 5)))
    
    100000 loops, best of 3: 2.12 µs per loop
    
    %timeit np.repeat(np.arange(1, 5), 4)
    
    1000000 loops, best of 3: 1.68 µs per loop
    

    Rory Daulton回答:

    %timeit [n for n in range(1,5) for repeat in range(4)]
    
    1000000 loops, best of 3: 1.9 µs per loop
    

    侏儒回答:

    %timeit list(i//4 for i in range(1*4, 5*4))
    
    100000 loops, best of 3: 2.47 µs per loop
    

    评论部分建议的跑路者:

    %timeit for i in range(1, 5): lst.extend([i] * 4)
    
    1000000 loops, best of 3: 1.46 µs per loop
    

    我的回答是:

    %timeit sorted(range(1,5)*4)
    
    1000000 loops, best of 3: 1.3 µs per loop
    
        4
  •  3
  •   jedwards    6 年前

    我想 chain + repeat 可能是你最好的选择。尽管如此,

    start = 1
    stop = 5
    repeat = 4
    
    x = list(i//repeat for i in range(start*repeat, stop*repeat))
    
    print(x)
    

    应该有效(至少对正参数有效)。

        5
  •  2
  •   Rory Daulton    6 年前

    我非常喜欢简单易懂的代码。有了这个理念,我会用

    [n for n in range(1,5) for repeat in range(4)]
    
        6
  •  1
  •   user1767754    6 年前

    我只是想提一下 extend 可能也是一个选择。也许没有一行列表理解那么漂亮,但是当 buckets 增加

    def listExtend():
        a = []
        for i in range(1,5):
            a.extend([i]*4)
        return a
    
    
    def listComprehension():
        return [[i,x] for i in range(1, 5) for x in range(4)]
    
    
    import timeit
    print(timeit.timeit(stmt="listComprehension()", setup="from __main__ import listComprehension", number=10**7))
    print(timeit.timeit(stmt="listExtend()", setup="from __main__ import listExtend", number=10**7))
    14.2532608
    8.78004566
    
        7
  •  1
  •   MSeifert    6 年前

    尽管需要安装一个包,但有一个选项是 itertation_utilities.replicate :

    >>> from iteration_utilities import replicate
    >>> list(replicate(range(1, 5), 4))
    [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
    

    如果你不想安装那个包 replicate 函数本质上等同于此函数:

    from itertools import repeat
    
    def replicate(items, repeats):
        for item in items:
            for _ in repeat(None, repeats):
                yield item
    

    为了防止您对性能感兴趣,我为几个(不是全部)建议的备选方案做了一些微基准测试:

    enter image description here

    就像你看到的那样 iteration_utilities 方法是 最快,而其他的方法都差不多一样快。

    有趣的是,在这些方法中 list.extend 接近速度最快,自定义生成器速度最慢。我没想到。

    下面是复制基准的代码:

    from iteration_utilities import replicate
    from itertools import chain, repeat
    import numpy as np
    
    def replicate_generator_impl(upper):
        for item in range(1, upper):
            for _ in repeat(None, 4):
                yield item
    
    def replicate_generator(upper):
        return list(replicate_generator_impl(upper))
    
    def iteration_utilities_replicate(upper):
        return list(replicate(range(1, upper), 4))
    
    def double_comprehension(upper):
        return [i for i in range(1, upper) for _ in range(4)]
    
    def itertools_chain(upper):
        return list(chain(*([x] * 4 for x in range(1, upper))))
    
    def itertools_chain_from_iterable(upper):
        return list(chain.from_iterable(repeat(i, 4) for i in range(1, upper)))
    
    def extend(upper):
        a = []
        for i in range(1, upper):
            a.extend([i] * 4)
        return a
    
    def numpy_repeat(upper):
        return np.repeat(np.arange(1, upper), 4)
    
    from simple_benchmark import benchmark
    
    funcs = [replicate_generator, iteration_utilities_replicate, double_comprehension, itertools_chain, itertools_chain_from_iterable, extend, numpy_repeat]
    arguments = {2**i: 2**i for i in range(1, 15)}
    b = benchmark(funcs, arguments, argument_name='size')
    b.plot()
    

    如果你想知道如果没有Numpy方法会是什么样子:

    enter image description here


    免责声明:我是 iteration_utilities simple_benchmark .