如何将具有偶数索引的项目移动到列表的末尾

How to move items with even index to the end of the list

lst = ['apple', 'orange', 'kiwi', 'ananas',
       'tea', 'coffee', 'milk', 'love', 'peace']

for i in range(len(lst)):
    if (i + 1) % 2 == 0:
        lst.append(lst[i])
        lst.pop(i)

基本上我想在这个列表的末尾添加索引为偶数的项目 它适用于第二项,但仍然不适用于其余项

一种简单的方法是使用理解来构建一个新列表:

lst2 = [v for i, v in enumerate(lst) if i%2 == 0] + \
       [v for i, v in enumerate(lst) if i%2 != 0]

但可以就地更改列表。规则是从列表的末尾开始,以便在删除元素时不改变索引的奇数

last = len(lst) - 1   # when an element is popped, the list loses one element
for i in range(len(lst), 0, -1):
    if (i % 2) == 0:
        val = lst.pop(i - 1)       # remove element with even index
        lst.insert(last, val)      # insert it before last inserted
        last -= 1

您的方法存在的问题是元素在您移动第一个元素后移动。因此,当您位于下一个具有“偶数”索引的元素时,该元素最初位于奇数索引处。因此,在移动第一个元素后,您可以直接继续下一个索引处的元素,该元素之前是 two 个索引,然后再移动下一个,依此类推,因为一半 列表中的索引。

这是一个示例,使用数字列表可以更容易地看到发生了什么。如果您想要奇数索引,请使用 range(1, len(lst)//2+1).

lst = list(range(10))
for i in range(len(lst)//2):
    lst.append(lst.pop(i))
# [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]

然而,即使这可行,在迭代列表的同时修改列表通常是一个非常糟糕的主意,会导致很多麻烦。此外,重复 pop(i) 使得整个操作 O(n²).

相反,将列表的两个部分合并起来会更快更明智:

lst = list(range(10))
lst = lst[1::2] + lst[0::2]
# [1, 3, 5, 7, 9, 0, 2, 4, 6, 8]

(如果您需要更改列表“in-place”,例如,由于其他引用指向该列表,您可以使用对切片的赋值来替换列表的内容:lst[:] = ...。在不使用额外内存的意义上,这仍然不是“in-place”。但是如果列表太大以至于这是一个问题,那么 O(n²) 运行 时间可能会无论如何都是一个更大的问题。)

您可以使用 Python 的 wider-step 范围:

lst = lst[1::2] + lst[0::2]

加号的右侧表示“从第一个元素开始抓取每第二个元素”,左侧表示“从第二个元素开始抓取每个第二个元素”。这基本上重建了奇数元素在前,偶数元素在后的列表。

它甚至避免了使您的参考算法成为 O(n^2)

的昂贵 pops