Python非线性切片

时间:2017-10-30 10:19:08

标签: python slice

给定一个列表adjustStyles,我可以通过执行以下操作来对其进行切片:

a

然而,这只是线性切片。 例如,我想选择2的幂的索引。 不幸的是,这不起作用:

a[start:end:step]

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

修改: 主要是我需要这个来修改列表。 E.g。

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

5 个答案:

答案 0 :(得分:2)

您可以使用列表理解:

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)]

答案 1 :(得分:1)

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

    # 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]

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

这是你想要做的吗?

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)

  

修改:   主要是我需要这个来修改列表。 E.g。

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])