根据列表中的元素更改嵌套列表中的值

时间:2011-03-27 12:00:07

标签: wolfram-mathematica

我在mathematica中有一对值列表,例如List= {{3,1},{5,4}}

如果第二个元素未达到阈值,如何更改第一个元素(3& 5)。例如,如果第二部分低于2,那么我希望第一部分变为零。所以列表然后= {{0,1},{5,4}}。其中一些列表非常长,所以不幸的是,手动执行它不是一种选择。

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

您可能需要更改变量,因为您的问题有点令人困惑。但这就是主意; - )