Способ обновления 3 переменных в зависимости от четвертой в Mathematica

#wolfram-mathematica #max

#wolfram-mathematica #max

Вопрос:

Я определил три переменные 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!!*)
  

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

Комментарии:

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

2. Кроме того, меня смущает «наиболее близкое к новому значению 5», которое, я полагаю, будет равно 1, а не 10.

3. да, позвольте мне объяснить это правильно, я хочу обновить три переменных и наибольшее значение, поэтому предположим, что у меня есть a = 1, b = 2, c = 40, затем четвертая переменная d = 5, так что у меня будет a = 1, b = 2, c =5, потому что a, b близки к новому значению d

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

5. @cMinor Я помню вас по тегу MATLAB, и я вижу сильное влияние этого на ваш код Mathematica. Хотя процедурный код может быть полезен при начале изучения Mathematica, я бы настоятельно рекомендовал попутно изучить более идиоматические способы выполнения задач в Mathematica (см. Наши ответы о некоторых подходах, которые вы не видели на других языках). Это, несомненно, очень поможет вам, если вы углубитесь в это. В то же время, я думаю, что все трое из нас, кто ответил, были бы признательны за обратную связь…

Ответ №1:

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

 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 , которая была самой большой, была заменена новым значением.

Комментарии:

1. @Mr.Wizard Вы правы, мне не нужно ReleaseHold . HoldFirst является только атрибутом updateList и используется в первом экземпляре list . Во второй и третьей — list аргумент ReplaceAll и Max соответственно, и, следовательно, этот атрибут не выполняется.

2. Удалите свой комментарий, прежде чем Леонид его увидит. Он всем расскажет! :->

3. Это просто несправедливо. Теперь у вас более 50 голосов впереди меня. Возможно, мне придется обратиться к темной стороне, чтобы бороться с этим…

4. я оставил тебя в пыли, не так ли? : D На самом деле это первый раз, когда я когда-либо приближался к 100 голосам за 30 дней в mma и фактически близок к серебру. Когда я начинал, я думал, что к настоящему времени у меня будет золото в MATLAB, но, похоже, я потерял к нему интерес. Я серьезно не отвечал там с июня (так что больше времени для mma: D). Но если серьезно, я вижу, что в ближайшие пару месяцев я буду очень занят, так что запускайте tortise, запускайте!

5. К сожалению, я сам буду очень занят, поэтому поймать вас будет сложно, несмотря на ваши короткие ноги … 🙂 У меня также никогда не было 100 голосов за 30 дней, точка. Но я не участвовал почти так же, как вы.

Ответ №2:

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

 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]amp; @ 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:

Вероятно, это не лучший способ решения этой проблемы,

 a = 1; b = 10; c = 0;
Position[#, Max@#] amp;@{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 amp;]]amp;@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}