Changing values in nested lists according to elements in the list

做~自己de王妃 提交于 2019-12-10 09:44:46

问题


I have a list of pairs of values in mathematica, for example List= {{3,1},{5,4}}.

How do I change the first element (3 & 5) if the second element does not reach a threshold. For example, if the second parts are below 2 then i wish the first parts to go to zero. so that list then = {{0,1},{5,4}}. Some of these lists are extremely long so manually doing it is not an option, unfortunately.


回答1:


Conceptually, the general way is to use Map. In your case, the code would be

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}}

The # symbol here stands for the function argument. You can read more on pure functions here. Double square brackets stand for the Part extraction. You can make it a bit more concise by using Apply on level 1, which is abbreviated by @@@:

In[27]:= {If[#2 < thr, 0, #], #2} & @@@ lst

Out[27]= {{0, 1}, {5, 4}}

Note however that the first method is several times faster for large numerical lists. An even faster, but somewhat more obscure method is this:

In[29]:= Transpose[{#[[All, 1]]*UnitStep[#[[All, 2]] - thr], #[[All, 2]]}] &[lst]

Out[29]= {{0, 1}, {5, 4}}

It is faster because it uses very optimized vectorized operations which apply to all sub-lists at once. Finally, if you want the ultimate performance, this procedural compiled to C version will be another factor of 2 faster:

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"] 

You use it as

In[32]:= fn[lst, 2] 

Out[32]= {{0, 1}, {5, 4}}

For this last one, you need a C compiler installed on your machine.




回答2:


Another alternative: Apply (@@@, Apply at level 1) and Boole (turns logical values in 1's and 0's):

lst = {{3, 1}, {5, 4}};
{#1 Boole[#2 >= 2], #2} & @@@ lst



回答3:


An alternative approach might be to use substitution rules, and attach a condition (/;)

lst = {{3, 1}, {5, 4}};

lst /. {x_, y_ /; y < 2} -> {0, y}

output:

{{0, 1}, {5, 4}}




回答4:


Assuming that your matrix is 2x2 and by second elemnt you mean the second row: This should work:

If[A[[2, 1]] < 2 || A[[2, 2]] < 2, A[[2,1]] = 0 ]; A

You may have to change the variables, since your questions is kind of confusing. But that's the idea ;-)



来源:https://stackoverflow.com/questions/5449065/changing-values-in-nested-lists-according-to-elements-in-the-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!