python - 仅使用常量python更改矩阵中的嵌套元素

标签 python multidimensional-array functional-programming stateless

嗨,我正在使用 python 中的矩阵,称之为a:

    a = [
         [0,0,0],
         [0,0,0],
         [0,0,0]
        ]

我想将第一列第二行的元素 (a[1][0]) 更改为 1,产生以下结果:

    a = [
         [0,0,0],
         [1,0,0],
         [0,0,0]
        ]

您当然可以通过以下方式轻松完成此任务:

    a[1][0] = 1

不幸的是,我是个疯子,想完成这个纯粹的功能:) 条件是:

  1. 变量状态不会改变,您应该能够用常量替换所有变量。
  2. 不使用状态完整运算符,例如 for in
  3. 变量 a 元素发生更改后的结果将存储在第二个变量 b 中,而不会更改 a
  4. 该解决方案不应使用任何导入或依赖项。

想要的结果应该是这样的:

    a = [
         [0,0,0],
         [0,0,0],
         [0,0,0]
        ]
    
    b = someOperation(a)
    
    assert a == [[0,0,0],[0,0,0],[0,0,0]]
    assert b == [[0,0,0],[1,0,0],[0,0,0]]
    # the above asserts should not trigger

有人知道我的问题的(纯功能性)解决方案吗? 提前致谢。

最佳答案

如果您想要纯粹的函数式方式来执行此类操作,您可能需要考虑如何在 Haskell 中执行此操作。 - 函数式编程的黄金标准。

对于小型的临时问题,如果您需要通过索引访问元素,通常会使用数字生成器压缩您的数据序列:

ghci> zip [0..] "abc"
[(0,'a'),(1,'b'),(2,'c')]

您可以在 Python 中执行相同的操作:

from itertools import count

def index_list(lst):
    return zip(count(), lst)

'abc'上使用它:

>>> list(index_list('abc'))
[(0, 'a'), (1, 'b'), (2, 'c')]

(在上面的示例中我仅使用 list 来显示结果。)

同样,您可以索引包含矩阵的嵌套列表:

def index_matrix(matrix):
    return index_list(map(index_list, matrix))

您现在有了一个元组映射的映射,其中元组的第一个元素是行或列索引,第二个元素是索引的值。

我们可以使用 OP 的输入在 Haskell 中执行相同的操作:

ghci> fmap (fmap (zip [0..])) $ zip [0..] [[0,0,0],[0,0,0],[0,0,0]]
[(0,[(0,0),(1,0),(2,0)]),(1,[(0,0),(1,0),(2,0)]),(2,[(0,0),(1,0),(2,0)])]

index_matrix Python 函数在概念上产生相同形状的输出,但由 zip 和 map 对象组成。

由于 index_matrix 已对行和列进行索引,因此您现在可以迭代 map 的 map 并替换特定行和列处的值:

def replace_in_matrix(matrix, row, col, value):
    return map(lambda r:
        map(lambda c:
            value if r[0] == row and c[0] == col else c[1], r[1]), index_matrix(matrix))

在 OP 矩阵上尝试一下:

>>> m = [[0,0,0],[0,0,0],[0,0,0]]                                         
>>> result = replace_in_matrix(m, 1, 0, 1)
>>> list(map(list, result))
[[0, 0, 0], [1, 0, 0], [0, 0, 0]]
>>> m
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

这也表明 m 保持不变。

Haskell 中的临时投影类似:

ghci> fmap (fmap snd)
      $ fmap snd
      $ fmap (\(i, rs) -> (i, fmap (\(j,  x) -> (j, if i == 1 && j == 0 then 1 else x)) rs))
      $ fmap (fmap (zip [0..]))
      $ zip [0..] [[0,0,0],[0,0,0],[0,0,0]]
[[0,0,0],[1,0,0],[0,0,0]]

(我插入了一些换行符以稍微提高可读性。)

关于python - 仅使用常量python更改矩阵中的嵌套元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74693103/

相关文章:

python - 如何使用 H5PY 将 HDF5 文件导出到 NumPy?

python - 如何将一列的不同行与 pandas 中的 Levenshtein 距离度量进行比较?

java - 这是在java中添加图书列表的最佳方式

c# - 如何使用 Deedle 进行基于行的处理(帧输入和帧输出)

functional-programming - 是否有纯粹的声明性通用编程语言?

python - ctypes 中的结构内联合语法

python - 正则表达式按最后一次出现的模式拆分字符串

javascript - 将数组添加到二维数组

matlab - 使用坐标向量访问矩阵值?

haskell - 使用 Reflex Platform 编译带有本地包的堆栈项目