在列表中的特定索引处插入元素并返回更新后的列表

Posted

技术标签:

【中文标题】在列表中的特定索引处插入元素并返回更新后的列表【英文标题】:Insert an element at a specific index in a list and return the updated list 【发布时间】:2013-01-31 11:32:43 【问题描述】:

我有这个:

>>> a = [1, 2, 4]
>>> print a
[1, 2, 4]

>>> print a.insert(2, 3)
None

>>> print a
[1, 2, 3, 4]

>>> b = a.insert(3, 6)
>>> print b
None

>>> print a
[1, 2, 3, 6, 4]

有没有一种方法可以获得更新的列表作为结果,而不是更新原始列表?

【问题讨论】:

b = a[:].insert(2,3) 看起来很短,不影响原始列表,而且描述性很强。 @mkoistinen 这对我不起作用。 >>> a = [1, 2, 3, 4] >>> b = a[:].insert(2, 5) >>> print b None 【参考方案1】:

l.insert(index, obj) 实际上并没有返回任何东西。它只是更新列表。

正如 ATO 所说,您可以使用b = a[:index] + [obj] + a[index:]。 但是,另一种方式是:

a = [1, 2, 4]
b = a[:]
b.insert(2, 3)

【讨论】:

如果你不能容忍 3 行可读代码,把它放在一个函数中并调用它。【参考方案2】:

最高效的方法

您也可以使用 slice 索引 在列表中插入元素。例如:

>>> a = [1, 2, 4]
>>> insert_at = 2  # Index at which you want to insert item

>>> b = a[:]   # Created copy of list "a" as "b".
               # Skip this step if you are ok with modifying the original list

>>> b[insert_at:insert_at] = [3]  # Insert "3" within "b"
>>> b
[1, 2, 3, 4]

对于在给定索引处同时插入多个元素,您只需使用要插入的多个元素的list。例如:

>>> a = [1, 2, 4]
>>> insert_at = 2   # Index starting from which multiple elements will be inserted

# List of elements that you want to insert together at "index_at" (above) position
>>> insert_elements = [3, 5, 6]

>>> a[insert_at:insert_at] = insert_elements
>>> a   # [3, 5, 6] are inserted together in `a` starting at index "2"
[1, 2, 3, 5, 6, 4]

了解更多切片索引,可以参考:Understanding slice notation。

注意:在 Python 3.x 中,slice indexinglist.index(...) 之间的性能差异显着减小,两者几乎相等.但是,在 Python 2.x 中,这种差异非常明显。我在这个答案后面分享了性能比较。


使用列表理解的替代方案 (但在性能方面非常慢)

作为替代方案,也可以使用 list comprehensionenumerate 来实现。 (但请不要这样做。这只是为了说明)

>>> a = [1, 2, 4]
>>> insert_at = 2

>>> b = [y for i, x in enumerate(a) for y in ((3, x) if i == insert_at else (x, ))]
>>> b
[1, 2, 3, 4]

所有解决方案的性能比较

这是timeit 将所有答案与 Python 3.9.1 和 Python 2.7.16 上的 1000 个元素列表的比较。答案按两个 Python 版本的性能顺序列出。

Python 3.9.1

    My answer 使用切片插入 - 最快(每个循环 2.25 微秒)

    python3 -m timeit -s "a = list(range(1000))" "b = a[:]; b[500:500] = [3]"
    100000 loops, best of 5: 2.25 µsec per loop
    

    Rushy Panchal's answer 使用list.insert(...) 获得最多票数 - 第二(每个循环 2.33 微秒)

    python3 -m timeit -s "a = list(range(1000))" "b = a[:]; b.insert(500, 3)"
    100000 loops, best of 5: 2.33 µsec per loop
    

    ATOzTOA's accepted answer 基于切片列表的合并 - 第三个(每个循环 5.01 微秒)

    python3 -m timeit -s "a = list(range(1000))" "b = a[:500] + [3] + a[500:]"
    50000 loops, best of 5: 5.01 µsec per loop
    

    My answerList Comprehensionenumerate - 第四 (非常慢,每个循环 135 微秒)

    python3 -m timeit -s "a = list(range(1000))" "[y for i, x in enumerate(a) for y in ((3, x) if i == 500 else (x, )) ]"
    2000 loops, best of 5: 135 µsec per loop
    

Python 2.7.16

    My answer 使用切片插入 - 最快(每个循环 2.09 微秒)

    python -m timeit -s "a = list(range(1000))" "b = a[:]; b[500:500] = [3]"
    100000 loops, best of 3: 2.09 µsec per loop
    

    Rushy Panchal's answer 使用list.insert(...) 获得最多票数-第二(每个循环2.36 µsec)

    python -m timeit -s "a = list(range(1000))" "b = a[:]; b.insert(500, 3)"
    100000 loops, best of 3: 2.36 µsec per loop
    

    ATOzTOA's accepted answer 基于切片列表的合并 - 第三个(每个循环 4.44 微秒)

    python -m timeit -s "a = list(range(1000))" "b = a[:500] + [3] + a[500:]"
    100000 loops, best of 3: 4.44 µsec per loop
    

    My answerList Comprehensionenumerate - 第四(非常慢,每个循环 103 微秒)

    python -m timeit -s "a = list(range(1000))" "[y for i, x in enumerate(a) for y in ((3, x) if i == 500 else (x, )) ]"
    10000 loops, best of 3: 103 µsec per loop
    

【讨论】:

我真的很喜欢这个结果,因为它很容易扩展到解决问题,如果我想将值 3, 3.5 插入到该列表中(按顺序)-> a[2:2] = [3,3.5]。很整洁【参考方案3】:

我得到的最短的:b = a[:2] + [3] + a[2:]

>>>
>>> a = [1, 2, 4]
>>> print a
[1, 2, 4]
>>> b = a[:2] + [3] + a[2:]
>>> print a
[1, 2, 4]
>>> print b
[1, 2, 3, 4]

【讨论】:

代码行数并不是衡量代码质量的好方法。由于性能和可读性的原因,这种方法存在缺陷。 可以a= a[:2] + [3] + a[2:]吗?【参考方案4】:

最干净的方法是复制列表,然后将对象插入到副本中。在 Python 3 上,这可以通过 list.copy 完成:

new = old.copy()
new.insert(index, value)

在 Python 2 上,可以通过 new = old[:] 复制列表(这也适用于 Python 3)。

就性能而言,与其他提议的方法没有区别:

$ python --version
Python 3.8.1
$ python -m timeit -s "a = list(range(1000))" "b = a.copy(); b.insert(500, 3)"
100000 loops, best of 5: 2.84 µsec per loop
$ python -m timeit -s "a = list(range(1000))" "b = a.copy(); b[500:500] = (3,)"
100000 loops, best of 5: 2.76 µsec per loop

【讨论】:

【参考方案5】:

这是添加单个项目的方法,特定索引中的单个项目将列表与另一个列表连接

>>> expences = [2200, 2350, 2600, 2130, 2190]
>>> expences.append(1980)
>>> expences
[2200, 2350, 2600, 2130, 2190, 1980]

>>> expences.insert(1, 1200)

>>> expences
[2200, 1200, 2350, 2600, 2130, 2190, 1980]

>>> newElm = [2550, 2123, 2430]
>>> expences.extend(newElm)
>>> expences
[2200, 1200, 2350, 2600, 2130, 2190, 1980, 2550, 2123, 2430]
>>> 

【讨论】:

【参考方案6】:

使用Python list insert() method。用法:

#语法

insert() 方法的语法 -

list.insert(index, obj)

#参数

index - 这是需要插入对象 obj 的索引。 obj - 这是要插入给定列表的对象。

#返回值 此方法不返回任何值,但它在给定索引处插入给定元素。

例子:

a = [1,2,4,5]

a.insert(2,3)

print(a)

返回[1, 2, 3, 4, 5]

【讨论】:

这不能回答问题。 问题很具体:Is there anyway I can get the updated list as result, instead of updating the original list in place? 你的回答正好相反。

以上是关于在列表中的特定索引处插入元素并返回更新后的列表的主要内容,如果未能解决你的问题,请参考以下文章

如何替换python列表特定索引处的值?

从现有列表中特定索引处的元素创建新列表

列表元素操作

从 SwiftUI 中的列表中删除绑定

使用节点js的地图中列表中特定索引处的Dynamodb sdk更新条目

第二章第三题