Как сопоставить функцию только одной записи в списке? - PullRequest
0 голосов
/ 23 декабря 2011

Я учусь использовать карту больше (чтобы стать более функциональным программистом). Похоже, что Map требуется список в качестве выражения, к которому будет применяться функция. Если выражение не является списком, оно не устраивает.

Я использую NumberForm в этом примере, чтобы проиллюстрировать, что я имею в виду:

Я могу отобразить NumberForm на весь список, хорошо:

data = {1, 2, 3}
Map[NumberForm[#, {3, 2}] &, data]

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

data = {1, 2, 3}
Map[NumberForm[#, {3, 2}] &, data[[1]] ]

Возвращенный результат НЕ отформатирован. То же, что и исходные данные. т.е. я получаю «1», а не «1,00», как в других примерах.

Чтобы решить, я добавил дополнительно {}

data = {1, 2, 3}
Map[NumberForm[#, {3, 2}] &, {data[[1]]} ]

теперь работает (нужно просто удалить {} из результата, используя First).

Итак, я подумал, тогда почему бы не добавить этот дополнительный {} все время и удалить его в конце? Таким образом, мне не нужно беспокоиться о том, что то, с чем я работаю в функции Map'ing, не является списком, как в примере выше?

Итак, все мои примеры станут такими:

data = {1, 2, 3}
First@Map[NumberForm[#, {3, 2}] &, { data } ]
First@Map[NumberForm[#, {3, 2}] &, { data[[1]] } ]

Таким образом, код будет работать на все, и мне не нужно делать специальную проверку перед использованием Map, если то, к чему я применял Map, является списком или нет.

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

Ответы [ 4 ]

3 голосов
/ 23 декабря 2011

Возможно, я не понимаю вашего намерения, но если вы ищете Map функцию только для определенной записи в списке, тогда MapAt - это функция, которую вы ищете за. Пример:

MapAt[NumberForm[#, {3, 2}] &, data, 1]
Out[1]= {1.00,2,3}

Здесь функция была применена только к первому элементу в списке.

2 голосов
/ 23 декабря 2011

Это кажется странным вопросом. Зачем писать First@Map[f, { x } ], когда можно просто написать f @ x?

Как получилось, что второй аргумент Map может быть любой формы?

Возможно, вы найдете значение в отображении по уровням с конца:

Map[f, {x, y, z}, {-1}]

Map[f, x, {-1}]

Будьте осторожны с этим, как будто элементы списка не атомарны, вы получите неожиданные результаты.

В качестве альтернативы вы можете написать:

data = {1, 2, 3};

data /. n_?NumberQ :> NumberForm[n, {3, 2}]

data[[1]] /. n_?NumberQ :> NumberForm[n, {3, 2}]
2 голосов
/ 23 декабря 2011

Я вижу несколько разных вопросов

  1. Каковы различные способы Map?Неудивительно, потому что списки имеют основополагающее значение для работы Mathematica, существует множество способов их преобразования.Тем не менее, я не вижу прямого способа сказать Mathematica, что, учитывая f и {l1, l2, ...}, я получу {f@l1, l2, ...}.Если вы хотите применить f к первому элементу l (например, для проверки перед применением f ко всем l), вы также можете выполнить f/@l[[1;;1]].(edit @yoda упоминает, что MapAt имеет такое поведение, можно указать набор позиций, где нужно отобразить).
  2. Как работать с операндом, который реализует шаблон Composite (т. е. является либо элементомтипа т или список элементов типа т)?Естественный способ сделать это в Mathematica - дать вашему оператору атрибут Listable.Тогда, если мы определим: f[a_AtomicType], f[a:{_AtomicType..}] даст результаты f/@a

Правка - На самом деле, если f[a_AtomicType]:=something, f[a_List] даст результаты f/@a, даже еслинекоторые элементы не имеют заголовка AtomicType - т.е. функции Listable не проверяют, что все элементы списка имеют правило преобразования в терминах f.Если вы заботитесь об этом, вам нужно отдельно определить f[a:{_AtomicType..}]:=f/@a и не делать свою функцию Listable.

Кроме того, @Nasser, похоже, что поведение в вашем первом примере таково, потому что Map[f,a_AtomicType] возвращает a.Также обратите внимание, что Map может отображать выражения с любой головой, а не только List.

2 голосов
/ 23 декабря 2011

Это работает только потому, что NumberForm работает со списками:

NumberForm[{1, 2, 3}, {3, 2}]

дает

{1.00, 2.00, 3.00}

Map[f, {{a, b, c}}] просто отображает f на First[{{a,b,c}}], а именно:на {a,b,c};так что вы получите f[{a,b,c}].

Так что, к сожалению, добавление {} не будет работать вообще.

Простой способ сделать это - определить

ClearAll[map]
map[f_, head_[els__]] := Map[f, head[els]]
map[f_, el_] := f[el]

, откуда

map[f, {a, b, c}]
map[f, a]

предоставить

{f[a], f[b], f[c]}
f[a]

Однако это не позволяет использовать форму Map[f,expr,levelspec] (что, однако, достаточно просто реализовать).

Это также работает вэтот случай:

map[f, g[a, b, c]] == Map[f, g[a, b, c]]
(*
True
*)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...