Способ обновления 3 переменных в зависимости от четвертой в Mathematica - PullRequest
3 голосов
/ 26 октября 2011

Я определил три переменные a,b,c перед циклом while, затем вычислил новую переменную d.

Я хочу избавиться от наибольшего значения в трех переменных a,b,c, а затем заменить его значением d; Так что я могу сохранить наименьшие значения в оригинальных переменных.

a = 1;
b = 2;
c = 10;
While[ condition,

      compute d using  values of a b and c
      d = 4;      
      a = 1;
      b = 2;
      c = 4;  (*c = d *)


]

чтобы сделать это, я подумал получить максимум из трех переменных и затем обновить его в зависимости от того, какое значение имеет наибольшее значение.

a = 1;
b = 2;
c = 10;
d = 4;
temp  = Max[a, b];
maxim = Max[c, temp];
a = a; (*did not change*)
b = b; (*did not change*)
c = d = 4 (*changed!!*)

Итак, после этого произойдет новая итерация и обновятся три переменные ...

Ответы [ 3 ]

6 голосов
/ 26 октября 2011

Другой вариант выглядит следующим образом:

Clear@updateList
SetAttributes[updateList, HoldFirst]    
updateList[list_, value_] := 
     Module[{listMax = Max@list}, 
      list = (list /. listMax -> value);]

Теперь, если я определю переменные, как в вашем случае, и использую функцию:

a = 1; b = 10; c = 0;
updateList[{a,b,c},5];
{a,b,c}

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

Вы можете видеть, что переменная b, который был самым большим, был заменен новым значением.

6 голосов
/ 26 октября 2011

Если вы можете принять значения в списке (массиве), а не в отдельных именованных символах, и если вы действительно имеете в виду «самое близкое», а не наибольшее, то вы можете сделать что-то вроде этого:

vars = {1, 10, 0};

vars = ReplacePart[vars, Position[vars, Nearest[vars, 5][[1]]] -> 5];

vars
(* Out=  {5, 10, 0} *)

Это также предполагает, что значения являются уникальными, или , которые вы хотите заменить всеми соответствующими значениями (например, если в этом примере более одного 1 в списке).

Если вам всегда чем заменить наибольшее значение, то вы могли бы Max[vars] вместо Nearest.


В свете обновленного описания проблемы, я предлагаю:

vars = {1, 10, 0};
d = 5;

vars = With[{m = Max[vars]}, If[d < m, vars /. m -> d, vars]]

Если вы хотите автоматизировать это, вы можете использовать:

SetAttributes[repmax, HoldFirst]
repmax[s_Symbol, n_?NumericQ] := If[n < #, s = s /. # -> n]& @ Max@s

Сейчас:

vals = {1, 10, 0};
repmax[vals, 5];

vals
{1, 5, 0}
vals = {1, 10, 0};
repmax[vals, 12];

vals
{1, 10, 0}
3 голосов
/ 26 октября 2011

Это, вероятно, не лучший способ решить эту проблему,

a = 1; b = 10; c = 0;
Position[#, Max@#] &@{a, b, c}
{a, b, c} = ReplacePart[{a, b, c}, % -> 5]

Было бы лучше определить исходные значения в виде списка abc = {1, 10, 0} и затем заменить элемент max всписок.Как я заметил, мистер Волшебник только что сделал в своем ответе.

Вы также можете сделать что-то вроде

SetAttributes[ReplaceMax, HoldFirst]
ReplaceMax[list : {__Symbol}, val_] := Module[{pos},
  pos = Flatten@Position[#, Max@Select[#, N[#] \[Element] Reals &]]&@list;
  Do[Evaluate[(HoldPattern /@ Unevaluated@list)[[p]]] = val, 
     {p, pos}]]

Тогда

In[15]:= {a, b, c, d, e} = {1, 15, 6, 17 + I, x}; 
In[16]:= ReplaceMax[{a, b, c, d, e}, 5]
          {a, b, c, d, e}

Out[17]= {1, 5, 6, 17 + I, x}
...