wolfram-mathematica - 如何将运行中的每个值替换为运行前的整数

标签 wolfram-mathematica

使用Mathematica,我有一个列表:

l={0,0,0,1,2,0,0,0,1,0,0,0,2,0,0,0}

我想对上面的列表应用一个函数以获得以下内容:
{0,0,0,1,2,2,2,2,1,1,1,1,2,2,2,2}

本质上,我想用相同长度的游程替换0值的游程,但要在每次运行0s之前使用正整数的值。

我以为我可以使用FoldList轻松地做到这一点,但是我看不到解决方案的出路。

非常感谢。

最佳答案

这是您的测试 list :

tst = {0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0}

以下解决方案将是相当有效的:
In[31]:= Module[{n = 0}, Replace[tst, {0 :> n, x_ :> (n = x)}, {1}]]

Out[31]= {0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2}

它的工作方式如下:我们使用仅应用第一个匹配规则的事实。变量n存储模式匹配器在列表中运行期间遇到的最后一个非零值。最初,它设置为零。第一条规则将0替换为n的当前值。如果匹配,则进行替换,然后模式匹配器继续运行。如果不匹配,则我们有一个非零值,第二条规则适用,更新了n的值。由于Set赋值返回该值,因此将非零元素简单地放回去。该解决方案的 list 长度应具有线性复杂度,并且是IMO偶尔将副作用与规则混合使用的一个很好的例子。

编辑

这是一个功能版本:
In[56]:= Module[{n = 0}, Map[If[# != 0, n = #, n] &, tst]]

Out[56]= {0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2}

可以检查基于规则的版本对于大型列表的速度大约快4倍。然而,
这种形式的优点是可以很容易地使用Compile -d来提供出色的性能:
nzrunsC = 
 Compile[{{l, _Integer, 1}}, 
   Module[{n = 0}, Map[If[# != 0, n = #, n] &, l]], 
   CompilationTarget -> "C"]

In[68]:= tstLarge = RandomInteger[{0,2},{10000000}];

In[69]:= nzrunsC[tstLarge];//Timing
Out[69]= {0.047,Null}

In[70]:= Module[{n = 0},Map[If[#!=0,n = #,n]&,tstLarge]];//Timing
Out[70]= {18.203,Null}

这里的差异是几百倍,比基于规则的解决方案快一百倍。 OTOH,基于规则的解决方案也适用于符号列表,不一定是整数列表。

关于wolfram-mathematica - 如何将运行中的每个值替换为运行前的整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6968806/

相关文章:

wolfram-mathematica - 对所有表达水平进行排序

wolfram-mathematica - 以文本形式保存 Mathematica 表达式

performance - Mathematica 快速二维分箱算法

hashtable - Mathematica中的MemberQ

wolfram-mathematica - 如何在 Mathematica 笔记本中对齐注释?

wolfram-mathematica - setdelayed inside manipulate 产生一个评估循环。为什么?

wolfram-mathematica - 保存 FittedModel 有问题

wolfram-mathematica - 如何在使用 DeleteCases 时删除额外的 {}

java - J/Link 中 "if"语句的正确语法

wolfram-mathematica - Convolve 在 Mathematica 中使用插值函数