【问题标题】:Slicing list the other way around?反过来切片列表?
【发布时间】:2017-06-21 13:05:16
【问题描述】:

我有这个清单:

arr = [1, 2, 3, 4, 5, 6]

我想做的是创建一个新列表,其中包含从索引 5 到索引 1 的值。

输出将是:

[6, 1, 2]

这就是我所做的:

output = arr[5:] + arr[:2]

但我想知道是否有另一种切片方法。

就像一个普通的切片,例如:

output = arr[5:1]

但我知道这行不通,因为我已经这样做了。请你帮助我好吗?

【问题讨论】:

  • 据我所知这是不可能的。
  • "...输出将是:[6, 1, 2]..." 会让我阅读您的问题的次数减少。
  • 问题不清楚:您是要删除索引 1 和 5 之间的内容(如您预期的输出所示)还是从 5 开始并循环回 0?
  • @healthyPAPAYA 所以你想要[1,2,6][6,1,2]
  • @healthyPAPAYA 好的,好节目。不过,那是在浪费这些穷人的时间。你可以看看我的回答。

标签: python slice


【解决方案1】:

据我所知,在不编写您自己的自定义代码的情况下执行此操作似乎是不可能的。 Python 不会环绕列表。

不过,您可以创建一个自定义生成器来做您想做的事:

>>> def cycle(l, start=0):
...     l = l[start:] + l[:start]
...     while True:
...         x = l.pop(0)
...         yield x
...         l.append(x)
... 
>>> k = cycle(a, 5)
>>> next(k)
6
>>> next(k)
1
>>> next(k)
2

示例由于 OP 的帖子更改而回滚。

这是一个改进的版本,它将考虑您希望从生成器中获取的数字元素:

>>> def cycle(l, start=0, iters=None):
...     l = l[start:] + l[:start]
...     i = 0
...     while True:
...         if iters is not None and i == iters:
...             raise StopIteration
...         x = l.pop(0)
...         yield x
...         l.append(x)
...         i += 1
... 
>>> a = [1, 2, 3, 4, 5, 6]
>>> list(cycle(a, start=5, iters=3))
[6, 1, 2]

【讨论】:

  • 他们想要1, 2, 6,而不是6, 1, 2
  • 看起来这是一个错字,他们确实想要6, 1, 2
  • @jadsq 哈哈。不管。回滚很简单。
  • itertools.cycleitertools.islice 一起使用更容易
  • @Chris_Rands 使用itertools.cycle,灵活性会降低。
【解决方案2】:

更新:

向左旋转 n 个元素(或向右旋转负 n)并切片你想要的元素数

L = L[n:] + L[:n] # rotate left n elements

在你的例子中,n 是 5:

>>> output = arr[5:] + arr[:5]
>>> output[:3]
[6, 1, 2]

上一页

>>> arr = [1, 2, 3, 4, 5, 6]
>>> output = arr[:]
>>> del output[2:5]
>>> output
[1, 2, 6]
>>> 

【讨论】:

  • @Coldspeed 6,1,2 不是 6,2,1
  • 这会创建一个与第一个大小相同的新列表,然后对 that 进行切片。是不是有点低效?
  • 只有当你与 output = arr[5:] + arr[:2] 比较时效率低下
  • 这就是我要与之比较的...如果列表大小为 GB 怎么办?
  • 别担心,coldspeed 也有同样的问题。尽管他的借口是他的生成器可能会产生任意数量的元素。
【解决方案3】:

创建一个函数来为您分割输入数组并将两个部分附加在一起以获得所需的列表。

def cyc_slice(lst, start, n): 
    return lst[start:] + lst[:(start+n)%len(lst)]

与其他两个答案不同,这不会对您不想要的所有列表元素进行多余的复制。

>>> arr=[1,2,3,4,5,6]
>>> cyc_slice(arr, 5, 3)
[6, 1, 2]

还有一个改进的迭代器解决方案:

def cycle(l, start=0, n=None):
    if not l:
        return
    idx = start-1
    end = (idx + n) % len(l) if n else -1
    while idx != end:
        idx+=1
        try:
            x = l[idx]
        except IndexError:
            idx = 0
            x = l[idx]
        yield x

当提供计数时,它将提供那么多元素。否则,它可以继续循环。这会在适当的位置迭代列表,因此不会将任何元素分配到内存(除非您从中创建列表)

>>> list(cycle(arr,5,3))
[6, 1, 2]

【讨论】:

    猜你喜欢
    • 2016-03-09
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    • 2010-12-14
    • 2020-03-10
    相关资源
    最近更新 更多