Изменение значений во вложенных списках в соответствии с элементами списка - PullRequest
3 голосов
/ 27 марта 2011

У меня есть список пар значений в Mathematica, например, List= {{3,1},{5,4}}.

Как мне изменить первый элемент (3 и 5), если второй элемент не достигает порогового значения.Например, если вторые части ниже 2, то я бы хотел, чтобы первые части обнулились.так что список тогда = {{0,1},{5,4}}.Некоторые из этих списков очень длинные, поэтому, к сожалению, делать это вручную нельзя.

Ответы [ 4 ]

9 голосов
/ 27 марта 2011

Концептуально, общий способ заключается в использовании Карта . В вашем случае код будет

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

Символ # здесь обозначает аргумент функции. Вы можете прочитать больше о чистых функциях здесь . Двойные квадратные скобки означают извлечение Part . Вы можете сделать это немного более кратким, используя Apply на уровне 1, который сокращается до @@@:

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, будет еще в 2 раза быстрее:

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, установленный на вашем компьютере.

3 голосов
/ 27 марта 2011

Другой вариант: Apply (@@@, Apply на уровне 1) и Boole (превращает логические значения в 1 и 0):

lst = {{3, 1}, {5, 4}};
{#1 Boole[#2 >= 2], #2} & @@@ lst
2 голосов
/ 27 марта 2011

Альтернативным подходом может быть использование правил подстановки и добавление условия (/;)

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

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

output:

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

1 голос
/ 27 марта 2011

Предполагая, что ваша матрица имеет размер 2x2, а под вторым элементом вы подразумеваете вторую строку: Это должно сработать:

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

Возможно, вам придется изменить переменные, поскольку ваши вопросы немного запутаны.Но это идея; -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...