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

Python非线性切片

  •  1
  • Pigna  · 技术社区  · 8 年前

    给出一个列表 a ,我可以通过以下操作进行切片:

    a[start:end:step]
    

    然而,这只是线性切片。 不幸的是,这不起作用:

    a[slice(2**x for x in range(len(a))]
    

    当需要非线性切片时,有没有办法避免循环?

    : 主要是我需要这个来修改列表。例如。

    a[*non-linear-slicing*] = [*list-with-new-values*]
    
    5 回复  |  直到 8 年前
        1
  •  2
  •   Neo    8 年前

    您可以使用列表理解:

    is_power_of_two = lambda num: num != 0 and ((num & (num - 1)) == 0)
    print [item for i, item in enumerate(a) if is_power_of_two(i)]
    
        2
  •  1
  •   Stefan Pochmann    8 年前

    编辑 : 主要是我需要这个来修改列表。例如。

    a[*non-linear-slicing*] = [*list-with-new-values*]
    

    太棒了然后我们可以使用新值列表来驱动这件事。演示:

    >>> a = range(17)
    >>> newvals = ['foo', 'bar', 'baz', 'qux']
    
    >>> for i, val in enumerate(newvals):
            a[2**i] = val
    
    >>> a
    [0, 'foo', 'bar', 3, 'baz', 5, 6, 7, 'qux', 9, 10, 11, 12, 13, 14, 15, 16]
    

    zip 而不是 enumerate :

    >>> a = range(17)
    >>> indexes = [1, 2, 4, 8]
    >>> newvals = ['foo', 'bar', 'baz', 'qux']
    >>> for i, val in zip(indexes, newvals):
            a[i] = val
    
    >>> a
    [0, 'foo', 'bar', 3, 'baz', 5, 6, 7, 'qux', 9, 10, 11, 12, 13, 14, 15, 16]
    

    既然你刚刚提到了来自R,也许你想使用NumPy,它确实支持这样的索引:

    >>> import numpy as np
    >>> a = np.arange(13)
    >>> a[[1, 2, 4, 8]] = [111, 222, 444, 888]
    >>> a
    array([  0, 111, 222,   3, 444,   5,   6,   7, 888,   9,  10,  11,  12])
    
        3
  •  1
  •   Adirio Raed Shomali    8 年前

    这就是你想要做的吗?

    a = [0,1,2,3,4,5,6,7,8,9]
    a[1],a[2],a[4],a[8] = [11,12,14,18]
    # a = [0,11,12,3,14,5,6,7,18,9]
    

    我不知道如何建造 a[1],a[2],a[4],a[8] 一般来说,理解或生成器不起作用,因为它们不允许分配操作。

        4
  •  1
  •   Vasilis G.    8 年前

    我不确定这是否是你想要的,但你可以试试这个:

        # Example list
    l = [1,2,3,4,5,6,7,8]
    
    result = list(map(lambda y: l[y], list(filter(lambda x: (x>0 and (x & (x-1) == 0)),list(range(0,len(l)))))))
    print(result)
    

    结果是:

    [2, 3, 5]
    

    但如果我是你,我不会用它,因为它几乎不可读。

        5
  •  1
  •   Rockybilly    8 年前

    为什么要迭代整个列表,而您只需要 2 ** i th元素。这大大提高了复杂性。

    a = range(100)
    
    def two_power_slice(lst):
        result = []
        for i in xrange(len(lst)):
            j = 2 ** i
            if j > len(lst) - 1:
                break
            result.append(lst[j])      
        return result
    
    print two_power_slice(a)
    

    我认为你也可以使用对数来避免使用 if 总共

    编辑: 改进版本,修复错误。

    def two_power_slice(lst):
        if not lst: return lst
        result = []
        for i in xrange(int(math.ceil(math.log(len(lst), 2)))):
            result.append(lst[2 ** i])      
        return result