假设我有一个列表:
my_list = [[1,2,3],[4,5,6],[7,8,9]]
如何更改列表中的每个值而不执行操作?:
for x in range(0, 3):
for y in range(0, 3):
my_list[x][y] = -my_list[x][y]
我试图通过
来简化这一过程my_list = [[[-a, -b, -c] for [a, b, c] in d] for d in my_list]
但价值保持不变。
答案 0 :(得分:11)
另一种选择是使用内置的map
函数:
>>> my_list = [[1,2,3],[4,5,6],[7,8,9]]
>>> neg = lambda x: -x
>>> f = lambda x: map(neg, x)
>>> map(f, my_list)
[[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]
答案 1 :(得分:7)
许多答案都是关于创建列表的更改 copy ,但问题的字面含义是关于列表的就地修改。
以下是我的最佳就地列表更改解决方案版本:
def alter_elements(lst, func):
for i, item in enumerate(lst):
if isinstance(item, list):
alter_elements(item, func)
else:
lst[i] = func(item)
试运行:
>>> sample = [[1,2,3],[4,5,6],[7,8,9]]
>>> alter_elements(sample, lambda x: -x)
>>> print sample
>>> [[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]
没有列表副本。没有硬编码的界限。没有副作用的列表理解。
答案 2 :(得分:6)
可以为此问题编写更通用的解决方案。以下适用于Python 3.0,,无论嵌套级别如何。
让我们定义recursive_map
:
import collections
def recursive_map(f, iterable):
for e in iterable:
if isinstance(e, collections.Iterable):
yield recursive_map(f, e)
else:
yield f(e)
现在,请求的否定函数可以编码如下:
import functools
import operator
negate = functools.partial(recursive_map, operator.neg)
因此,对于一些任意嵌套的 iterables x
的集合,我们计算它的否定y
,如下所示:
y = negate(x)
<强>附录:强>
如用户chradcliffe所述,上面的negate
函数会生成一个生成器,其中可能包含其他生成器......等。要扩展/评估所有这些生成器,我们需要应用{{ 1}}给所有人。所以我们定义了另一个通用映射函数,这次是一个可以处理迭代本身的函数。
list()
现在,
def recursive_iter_map(f, iterable):
def rec(e):
if isinstance(e, collections.Iterable):
return recursive_iter_map(f, e)
else:
return e
return f(map(rec, iterable))
实际上会立即否定每个元素并返回完整的列表。
请注意,我们可以将嵌套的iterables集合视为树。每个iterable都是一个子树,而非迭代是叶子。因此,我定义的第一个函数适用于叶子,第二个函数适用于非叶子。
答案 3 :(得分:3)
通过“改变”我认为你的意思是“否定”(但你应该这么说)。
我注意到你在迭代二维数组的每个元素(列表列表)并将每个元素视为三个元素的列表......但实际上每个元素只是一个数字,在你的问题如上所述。所以我会做这样的事情:
my_list = [[-n for n in l] for l in my_list]
答案 4 :(得分:3)
试试这个:
my_list = [[-a, -b, -c] for [a, b, c] in my_list]
请注意,这会创建一个新列表,而不是更改列表。
答案 5 :(得分:1)
正如其他人所说,有两个“级别”的列表和一个“级别”的整数,所以两个循环给你一个int,而不是另一个列表。
为了比较,循环版本应为:
for x in range(0, 3):
for y in range(0, 3):
my_list[x][y] = -my_list[x][y]
这也修复了范围的界限。上限是独占的,不包括在内。
答案 6 :(得分:1)
虽然康斯坦丁的回答是正确的,但我会做出两项改进:
enumerate
并建立索引的速度不如创建列表副本并使用[:]
切片就地分配。所以这是我的替代方案,它也会修改列表和所有内部列表:
def lst_apply(lst, func, lvl):
if lvl:
for x in lst:
lst_apply(x, func, lvl - 1)
else:
lst[:] = [func(x) for x in lst]
>>> lst_apply(my_list, lambda x: -x, 1)
>>> my_list
[[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]
但我仍然相信,这里最好的方法是:
def simple_apply(lst, func):
lst[:] = [[func(x) for x in y] for y in lst]
timeit
结果:
simple_apply
:4.0s lst_apply
:5.4s alter_elements
:11.5s 答案 7 :(得分:1)
这很难看,但如果你真的想要,你可以使用列表理解来就地修改列表。
>>> my_list = [[1,2,3],[4,5,6],[7,8,9]]
>>> [[slist.__setitem__(i, -n) for i, n in enumerate(slist)] for slist in my_list]
[[None, None, None], [None, None, None], [None, None, None]]
>>> my_list
[[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]
for
循环当涉及副作用时,使用显式for
循环(如其他答案中所示)被认为是更好的样式。我认为for
循环样式的一个很好的形式是:
for nested_list in my_list:
for i, x in enumerate(nested_list):
nested_list[i] = -x
答案 8 :(得分:0)
如果您有一个3x3的数字数组,并且想要对其中的每个元素执行转换,我怀疑从长远来看,使用像NumPy / SciPy这样的数值库并使用矩阵可能会更好它提供的例程。如果您对高性能感兴趣,那么这将是必要的。 python的大部分灵活性可以在数组元素级别放弃,以换取优化的数值算法速度。
答案 9 :(得分:0)
lst 变量是指向列表 word_list 的指针。如果 i 的值在 set(lst) 中,则通过获取 i 的索引值并分配 j 来替换。
my_list = [[1,2,3],[4,5,6],[7,8,9]]
dictionary = {1: -1, 2: -2, 3: -3,4:-4,5:-5,6:-6,7:-7,8:-8,9:-9}
def replace_all(word_list, dictionary):
for i, j in dictionary.items():
for lst in word_list:
if i in set(lst):
print("index",lst.index(i),"replace",j)
lst[lst.index(i)] = j
print(word_list)
return word_list
result=replace_all(my_list, dictionary)
print("result",result)
输出:
index 0 replace -1
[[-1, 2, 3], [4, 5, 6], [7, 8, 9]]
index 1 replace -2
[[-1, -2, 3], [4, 5, 6], [7, 8, 9]]
index 2 replace -3
[[-1, -2, -3], [4, 5, 6], [7, 8, 9]]
index 0 replace -4
[[-1, -2, -3], [-4, 5, 6], [7, 8, 9]]
index 1 replace -5
[[-1, -2, -3], [-4, -5, 6], [7, 8, 9]]
index 2 replace -6
[[-1, -2, -3], [-4, -5, -6], [7, 8, 9]]
index 0 replace -7
[[-1, -2, -3], [-4, -5, -6], [-7, 8, 9]]
index 1 replace -8
[[-1, -2, -3], [-4, -5, -6], [-7, -8, 9]]
index 2 replace -9
[[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]
result [[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]