改变Python列表中的所有值?

时间:2009-03-28 22:15:05

标签: python

假设我有一个列表:

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]

但价值保持不变。

10 个答案:

答案 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)

虽然康斯坦丁的回答是正确的,但我会做出两项改进:

  1. 一般性并不总是最好的方式。如果更改功能应该在列表上工作怎么办?
  2. 使用enumerate并建立索引的速度不如创建列表副本并使用[:]切片就地分配。
  3. 所以这是我的替代方案,它也会修改列表和所有内部列表:

    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]]