Выполните операции для второго компонента каждого элемента в списке в Mathematica - PullRequest
4 голосов
/ 26 декабря 2011

Я могу использовать следующий способ для выполнения некоторых операций (в данном случае ToString) для первого компонента каждого элемента в списке:

{ToString@#[[1]], Rest@#}~Flatten~1 & /@ {{1, 2}, {3, 4, 5}}

Однако у меня есть несколько вопросов:

  • Это не работает для {ToString@#[[1]], Rest@#}~Flatten~1 & /@ {{1, 2}, 2, {3, 4, 5}} по очевидной причине. Как заставить это также работать в этот случай? Ожидаемый результат будет {{"1", 2}, 2, {"3", 4, 5}}.
  • Как это сделать для второго (или третьего и т. Д.) Компонента легко ? То есть Я хочу, чтобы вывод был {{0}, {1, "2"}, {3, "4", 5}, {6, "7", 9, 10}}
  • Есть ли способ использовать шаблон / правило (например, /.{#[[1]]->ToString[#[[1]]]}) для такой операции? Поэтому, пожалуйста, перечислите все решения, которые вы можете придумать, независимо от эффективности.

Большое спасибо!

Ответы [ 4 ]

5 голосов
/ 27 декабря 2011

Я не понимал, что это то же самое, что и основная функция Леонида, пока я не написал это. Возможно, это говорит о том, что это может быть немного более прозрачно, чем его довольно сложная функция.

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

Replace[lst, {a_, b__} :> {ToString@a, b}, 1]
{{"1", 2}, 2, {"3", 4, 5}}

Затем можно использовать {x:Repeated[_, {4}], a_, b__} :> {x, ToString@a, b}, 1] для пятого индекса и т. Д.

4 голосов
/ 27 декабря 2011

Следующая функция должна делать то, что вы хотите:

ClearAll[applyToAll];
applyToAll[f_, list_List, n_Integer] :=
   applyToAll[x_ :> f[x], list, n];
applyToAll[rule : (_Rule | _RuleDelayed), list_List, n_Integer] :=
  Replace[
      list, {left : Repeated[_, {n - 1}], el_, rest___} :> 
        {left, el /. rule, rest}, {1}];

и может принять правила. Например:

In[192]:= 
applyToAll[ToString, {{1,2},2,{3,4,5}},1]//InputForm
Out[192]//InputForm=  {{"1", 2}, 2, {"3", 4, 5}}

In[193]:= applyToAll[ToString,{{0},{1,2},{3,4,5},{6,7,9,10}},2]//InputForm
Out[193]//InputForm=  {{0}, {1, "2"}, {3, "4", 5}, {6, "7", 9, 10}}

In[194]:= applyToAll[x_?OddQ:>ToString[x],{{0},{1,2},{3,4,5},{6,7,9,10}},2]//InputForm
Out[194]//InputForm= {{0}, {1, 2}, {3, 4, 5}, {6, "7", 9, 10}}
2 голосов
/ 27 декабря 2011

Другим удобным методом может быть использование ReplacePart вместе с RuleDelayed

Например, для преобразования части 3 каждого подсписка (если он существует) в строку:

ReplacePart[#, 3 :>  ToString@#[[3]]] & /@ {{1, 2}, 
   2, {3, 4, 5}, {6, 7, 9, 10}} // InputForm

дает в качестве вывода:

{{1, 2}, 2, {3, 4, "5"}, {6, 7, "9", 10}}

Аналогично, чтобы превратить часть 1 каждого подсписка в строку:

ReplacePart[#, 1 :>  ToString@#[[1]]] & /@ {{1, 2}, 
   2, {3, 4, 5}} // InputForm

, что дает:

{{"1", 2}, 2, {"3", 4, 5}}

1 голос
/ 27 декабря 2011

В долгосрочной перспективе я думаю, что это может быть проще, даже если это не совсем то, что вы просили:

rep[f_, pos_][x_List] := MapAt[f, x, pos]
rep[__][x_] := x

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

rep[ToString, 2] /@ lst
{{1, "2"}, 2, {3, "4", 5}}

Вы можете добавить произвольные шаблоны и условия к определениюrep по мере необходимости.

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