如何替换python列表特定索引处的值?
Posted
技术标签:
【中文标题】如何替换python列表特定索引处的值?【英文标题】:How to replace values at specific indexes of a python list? 【发布时间】:2011-11-06 01:39:08 【问题描述】:如果我有一个清单:
to_modify = [5,4,3,2,1,0]
然后声明另外两个列表:
indexes = [0,1,3,5]
replacements = [0,0,0,0]
如何将to_modify
的元素作为indexes
的索引,然后将to_modify
中的对应元素设置为replacements
,即运行后indexes
应该是[0,0,3,0,1,0]
。
显然,我可以通过 for 循环做到这一点:
for ind in to_modify:
indexes[to_modify[ind]] = replacements[ind]
但是还有其他方法可以做到这一点吗?
我可以以某种方式使用operator.itemgetter
吗?
【问题讨论】:
您提到的循环解决方案有什么问题(我能看到的唯一问题是l
包含 m 范围之外的索引)?您能否为这个问题提供更多背景信息?
@dbr:我认为他想用 m 中的值替换由 l 中的索引索引的 s 中的值,所以这里的越界没有问题。
它包含超出 a 范围的索引,因为您正在访问 a[index],这不好。
@steabert:很好,我没有看到,因为我看不到所有 1 字母变量。
“Python 的切片对象”与这里提出的问题无关。
【参考方案1】:
你可以用字典来解决它
to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]
dic =
for i in range(len(indexes)):
dic[indexes[i]]=replacements[i]
print(dic)
for index, item in enumerate(to_modify):
for i in indexes:
to_modify[i]=dic[i]
print(to_modify)
输出将是
0: 0, 1: 0, 3: 0, 5: 0
[0, 0, 3, 0, 1, 0]
【讨论】:
你可以用dic = dict(zip(indexes, replacements))
替换第一个for循环。【参考方案2】:
您的代码最大的问题是它不可读。 Python 代码规则第一,如果它不可读,没有人会看它足够长的时间来从中获取任何有用的信息。始终使用描述性变量名称。差点没抓到你代码的bug,用好名字,慢动作回放风格再看一遍:
to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]
for index in indexes:
to_modify[indexes[index]] = replacements[index]
# to_modify[indexes[index]]
# indexes[index]
# Yo dawg, I heard you liked indexes, so I put an index inside your indexes
# so you can go out of bounds while you go out of bounds.
很明显,当您使用描述性变量名称时,您正在使用来自自身的值来索引索引列表,这在这种情况下没有意义。
此外,当并行迭代 2 个列表时,我喜欢使用 zip
函数(如果您担心内存消耗,也可以使用 izip
,但我不是那些迭代纯粹主义者之一)。所以试试这个吧。
for (index, replacement) in zip(indexes, replacements):
to_modify[index] = replacement
如果您的问题仅与数字列表有关,那么我会说@steabert 有您正在寻找的那些 numpy 东西的答案。但是,您不能将序列或其他可变大小的数据类型用作 numpy 数组的元素,因此如果您的变量 to_modify
中包含类似的内容,您最好使用 for 循环。
【讨论】:
是的,我更喜欢 zip-way,但我会使用 i,rep 作为运行值(我不喜欢一个字母的区别,但有时也使用它)。所以,我猜是 array 还是 zip 取决于情况。 是的,我也使用这样的缩短变量名,尤其是作为迭代中的值;我只是想强调,如果清晰很重要,使用一个完整的词并不可耻。 python 之禅说,“可读性很重要”。 添加到机器向往的评论...Zen of python - see pep 20.【参考方案3】:为什么不只是:
map(s.__setitem__, a, m)
【讨论】:
+1 相当优雅,但并不漂亮,也不是主流。很高兴看到这个来得这么晚。 很好,但是你仍然只有一个迭代器;) @steabert:是的,但是你不使用这个函数的结果很聪明;它有点违反了没有副作用的函数式编程原则,这很讽刺,因为map
本身就是python函数式编程范式的一部分。
@machine 向往:感谢您的建议。我从未考虑过map
的副作用。有时我只是把它当作 Array.forEach
的等价物,它没有 Python 实现。
@eph: 是的,如果你不知道的话,副作用只是一个用于函数所做的不涉及返回值的事情......所以即使是像输入这样的事情/output 总是基于副作用。不一定是坏事,这只是函数式编程en.wikipedia.org/wiki/Functional_programming 范式的一部分,尽量避免它们;你的函数所做的任何事情都应该在它的返回值中被捕获。 :)【参考方案4】:
对于a中的索引:
这将导致index
采用a
的元素 的值,因此将它们用作索引不是您想要的。在 Python 中,我们通过实际迭代来迭代容器。
“但是等等”,你说,“对于a
的每个元素,我需要使用m
的相应元素。没有索引我应该怎么做?”
简单。我们将a
和m
转换为对列表(a 中的元素,m 中的元素),并遍历这些对。这很容易做到——只需使用内置库函数zip
,如下:
for a_element, m_element in zip(a, m):
s[a_element] = m_element
要使其按照您尝试的方式工作,您必须获取要迭代的索引列表。这是可行的:例如,我们可以使用range(len(a))
。但不要那样做!这不是我们在 Python 中做事的方式。实际上,直接迭代你想要迭代的东西是一个美丽的、解放思想的想法。
operator.itemgetter 呢
这里并不真正相关。 operator.itemgetter
的目的是将索引的行为变成某种东西,变成类似函数的东西(我们称之为“可调用”),以便它可以用作回调(例如,用于排序或最小/最大操作)。如果我们在这里使用它,我们必须在每次循环中重新调用它来创建一个新的 itemgetter,这样我们就可以立即使用它一次并把它扔掉。在上下文中,这只是忙碌的工作。
【讨论】:
【参考方案5】:有点慢,但我认为可读:
>>> s, l, m
([5, 4, 3, 2, 1, 0], [0, 1, 3, 5], [0, 0, 0, 0])
>>> d = dict(zip(l, m))
>>> d #dict is better then using two list i think
0: 0, 1: 0, 3: 0, 5: 0
>>> [d.get(i, j) for i, j in enumerate(s)]
[0, 0, 3, 0, 1, 0]
【讨论】:
【参考方案6】:您可以使用operator.setitem
。
from operator import setitem
a = [5, 4, 3, 2, 1, 0]
ell = [0, 1, 3, 5]
m = [0, 0, 0, 0]
for b, c in zip(ell, m):
setitem(a, b, c)
>>> a
[0, 0, 3, 0, 1, 0]
它是否比您的解决方案更具可读性或效率?我不确定!
【讨论】:
不可读,因为你又使用了无用的变量名,哈哈!这是 Python,不是 Haskell【参考方案7】:numpy 具有允许您使用其他列表/数组作为索引的数组:
import numpy
S=numpy.array(s)
S[a]=m
【讨论】:
+1 哈哈,太好了,我刚把这个添加到我的帖子中,GJ。但我会争论这是否有必要。 好吧,一切都是有争议的,即使是短变量名还是长变量名,因为有时短变量名是可以的(如果在小函数中有意义的话)。至于 numpy 解决方案:对我来说,它更具可读性,并且对于大型数组,您正在使用 C 的强大功能:) 但是是的,只有在您从一开始就使用数组时才真正有用,因为将列表转换为数组需要时间。 我完全同意,这将取决于他首先为什么要这样做......但是如果他甚至没有真正使用数字数组,并且他有一个字典列表或像这样时髦的东西?想都别想。他的问题显然没有明确说明。 大声笑,我想我们被骗了...请参阅@eph 解决方案。以上是关于如何替换python列表特定索引处的值?的主要内容,如果未能解决你的问题,请参考以下文章