我在mathematica中有一对值列表,例如List= {{3,1},{5,4}}
。
如果第二个元素未达到阈值,如何更改第一个元素(3& 5)。例如,如果第二部分低于2,那么我希望第一部分变为零。所以列表然后= {{0,1},{5,4}}
。其中一些列表非常长,所以不幸的是,手动执行它不是一种选择。
答案 0 :(得分:9)
从概念上讲,一般方法是使用Map。在您的情况下,代码将是
In[13]:= lst = {{3, 1}, {5, 4}}
Out[13]= {{3, 1}, {5, 4}}
In[14]:= thr = 2
Out[14]= 2
In[15]:= Map[{If[#[[2]] < thr, 0, #[[1]]], #[[2]]} &, lst]
Out[15]= {{0, 1}, {5, 4}}
此处的#
符号代表函数参数。您可以阅读有关纯函数here的更多信息。双方括号代表Part提取。您可以在级别1上使用Apply使其更简洁,缩写为@@@
:
In[27]:= {If[#2 < thr, 0, #], #2} & @@@ lst
Out[27]= {{0, 1}, {5, 4}}
但请注意,对于大型数字列表,第一种方法的速度要快几倍。这是一个更快但更隐蔽的方法:
In[29]:= Transpose[{#[[All, 1]]*UnitStep[#[[All, 2]] - thr], #[[All, 2]]}] &[lst]
Out[29]= {{0, 1}, {5, 4}}
它更快,因为它使用非常优化的矢量化操作,一次应用于所有子列表。最后,如果你想要最终的性能,这个编译为C版本的程序将是另一个更快的因素:
fn = Compile[{{lst, _Integer, 2}, {threshold, _Real}},
Module[{copy = lst, i = 1},
For[i = 1, i <= Length[lst], i++,
If[copy[[i, 2]] < threshold, copy[[i, 1]] = 0]];
copy], CompilationTarget -> "C", RuntimeOptions -> "Speed"]
您将其用作
In[32]:= fn[lst, 2]
Out[32]= {{0, 1}, {5, 4}}
对于最后一个,您需要在计算机上安装C编译器。
答案 1 :(得分:3)
另一种选择:申请(@@@,在第1级申请)和布尔(在1和0中转换逻辑值):
lst = {{3, 1}, {5, 4}};
{#1 Boole[#2 >= 2], #2} & @@@ lst
答案 2 :(得分:2)
另一种方法可能是使用替换规则,并附加条件(/;)
lst = {{3, 1}, {5, 4}};
lst /. {x_, y_ /; y < 2} -> {0, y}
输出:
{{0,1},{5,4}}
答案 3 :(得分:1)
假设你的矩阵是2x2,那么你的意思是第二行: 这应该有效:
If[A[[2, 1]] < 2 || A[[2, 2]] < 2, A[[2,1]] = 0 ]; A
您可能需要更改变量,因为您的问题有点令人困惑。但这就是主意; - )