如何优化APL中无直接赋值对矩阵随机行应用函数f的实现?
嘿,这个问题我太熟悉了——原代码里的M⍳⍵确实是个痛点,毕竟它要在整个矩阵里搜当前行的位置,矩阵一大或者有重复行的时候,不仅慢,还可能因为重复行返回错误的索引(比如匹配到第一个相同的行,而不是当前处理的那一行)。
咱们来优化一下,核心思路就是直接拿到当前行的索引,不用搜索:
方案一:用左参数传递行索引(贴合原代码风格)
既然⍤1是逐行处理,我们可以把行索引作为左参数传给处理函数,这样函数里直接用⍺(当前行索引)和r比较,完全不需要搜索:
({(r=⍺)⊃(f⍵)⍵}⍤1)⍳⍴M ⊣ M
解释一下:
⍳⍴M生成行索引列表(比如5×5矩阵就是1 2 3 4 5)⍤1让函数逐行跑,此时⍺是当前行的索引,⍵是当前行的内容(r=⍺)判断是不是目标行,是的话取f⍵(处理后的行),否则直接返回原行⍵⊣ M是为了让左参数是行索引,右参数是原矩阵,保证函数能正确拿到⍺和⍵
如果想保留原代码里⍣操作符的风格,也可以这么写:
({f(⍣(r=⍺))⍵}⍤1)⍳⍴M ⊣ M
⍣(r=⍺)的意思是:只有当当前行索引等于r时,才应用f函数,否则直接返回原行。
方案二:直接构造新矩阵(更高效的无映射方式)
如果不想用逐行映射,也可以直接生成布尔掩码,替换目标行,全程不用赋值:
((⍳⍴M)∘.=r) ⊃¨ ⊂(f(r⌷M)),M
解释一下:
(⍳⍴M)∘.=r生成一个布尔向量,只有第r位是1,其他都是0⊂(f(r⌷M)),M把处理后的目标行和原矩阵打包成一个嵌套数组⊃¨根据布尔向量选择:1选处理后的行,0选原矩阵对应的行
这两种方案都解决了原代码的搜索问题,效率更高,逻辑也更可靠——再也不用担心重复行导致的索引错误啦!
内容的提问来源于stack exchange,提问作者Ian Martin
相关产品推荐
相关产品推荐

