Function Repository Resource:

MapAtPart

Source Notebook

Map different functions at particular positions

Contributed by: Faizon Zaman

ResourceFunction["MapAtPart"][{i1f1,,infn},expr]

applies fn to the element at position in in expr.

ResourceFunction["MapAtPart"][fs]

represents an operator form of ResourceFunction["MapAtPart"] that can be applied to an expression.

Details

The fi are applied in the order given.
The fi apply to individual elements as opposed to sequences of elements within the expression.
i can be any part specification supported by MapAt, as well as symbolic parts First, Last, Most, Rest, and Span.
The input expr can have any head, not just List.

Examples

Basic Examples (3) 

Apply f to the first element of a list and g to the second:

In[1]:=
ResourceFunction["MapAtPart"][{1 -> f, 2 -> g}, {x, y}]
Out[1]=

Apply func to the value of a Key in an Association:

In[2]:=
ResourceFunction["MapAtPart"][Key["A"] -> func, <|"A" -> x, "B" -> y|>]
Out[2]=

Use the operator form of MapAtPart:

In[3]:=
ResourceFunction["MapAtPart"][{1 -> f, 2 -> g}][{x, y}]
Out[3]=

Scope (7) 

Symbolic Part Specifications (3) 

Apply f to the First element of a list and g to the Rest:

In[4]:=
ResourceFunction["MapAtPart"][{First -> f, Rest -> g}, Range[3]]
Out[4]=

Apply f to Most of the list and g to the Last element:

In[5]:=
ResourceFunction["MapAtPart"][{Most -> f, Last -> g}, Range[3]]
Out[5]=

Apply f to the First element of the list and g to the Span of elements from position 3 onward:

In[6]:=
ResourceFunction["MapAtPart"][{First -> f, Span[3, All] -> g}, Range[5]]
Out[6]=

Use the shorthand (;;) syntax for Span:

In[7]:=
ResourceFunction["MapAtPart"][{First -> f, 3 ;; -> g}, Range[5]]
Out[7]=

MapAtPart on Associations (4) 

Apply f to the first value of an Association:

In[8]:=
ResourceFunction["MapAtPart"][1 -> f, <|"A" -> Range[2]|>]
Out[8]=

Apply f to Most of the values in an Association and g to the Last value of an Association:

In[9]:=
ResourceFunction[
 "MapAtPart"][{Most -> f, Last -> g}, <|"A" -> Range[1, 2], "B" -> Range[5]|>]
Out[9]=

Use an explicit Key:

In[10]:=
ResourceFunction["MapAtPart"][
 {"A" -> f, Key["C"] -> g},
 <|
  "A" -> Range[2],
  "B" -> Range[3],
  "C" -> Range[5]
  |>
 ]
Out[10]=

Specify a nested part:

In[11]:=
res = ResourceFunction["MapAtPart"][
  {{1, Key["A"]} -> f, {2, Last} -> g},
  {
   <|"A" -> Range[2], "B" -> Range[5]|>,
   <|"A" -> Range[3], "B" -> 3|>
   }
  ]
Out[11]=
In[12]:=
res // Dataset
Out[12]=

Properties and Relations (8) 

MapAtPart is implemented with Fold and MapAt; use FoldList to see intermediate steps:

In[13]:=
FoldList[MapAt[Keys[#2], #1, Values[#2]] &, Range[5], {f -> 1, g -> 3 ;;}]
Out[13]=
In[14]:=
ResourceFunction["MapAtPart"][{1 -> f, 3 ;; -> g}, Range[5]]
Out[14]=

MapAtPart[if,expr] is equivalent to MapAt[f,expr,i]:

In[15]:=
ResourceFunction["MapAtPart"][1 -> f, {x, y}]
Out[15]=
In[16]:=
MapAt[f, {x, y}, 1]
Out[16]=

Use multiple positions:

In[17]:=
ResourceFunction["MapAtPart"][{{1}, {3}, {5}} -> f, {a, b, c, d, e}]
Out[17]=
In[18]:=
MapAt[f, {a, b, c, d, e}, {{1}, {3}, {5}}]
Out[18]=

MapAtPart[if,expr] is equivalent to SubsetMap[Map[f],expr,i]:

In[19]:=
SubsetMap[Map[f], {a, b, c, d, e}, {1}]
Out[19]=
In[20]:=
ResourceFunction["MapAtPart"][1 -> f, {a, b, c, d, e}]
Out[20]=

Use multiple positions:

In[21]:=
SubsetMap[Map[f], {a, b, c, d, e}, {{1}, {3}, {5}}]
Out[21]=
In[22]:=
ResourceFunction["MapAtPart"][{{1}, {3}, {5}} -> f, {a, b, c, d, e}]
Out[22]=

MapAtPart[f,expr] is equivalent to Apply[f,expr]:

In[23]:=
ResourceFunction["MapAtPart"][f, {x, y}]
Out[23]=
In[24]:=
Apply[f, {x, y}]
Out[24]=

A position specification of All is equivalent to MapAt[f,expr,All] and also equivalent to Map[f,expr]:

In[25]:=
ResourceFunction["MapAtPart"][{All -> f}, {a, b, c, d, e}]
Out[25]=
In[26]:=
MapAt[f, {a, b, c, d, e}, All]
Out[26]=
In[27]:=
Map[f, {a, b, c, d, e}]
Out[27]=

If the right-hand side of a replacement wraps the bound expression, then ReplaceAt is also equivalent to the above when the part is All:

In[28]:=
ReplaceAt[{a, b, c, d, e}, el_ :> f[el], All]
Out[28]=

ReplacePart has access to indices but not elements:

In[29]:=
ReplacePart[{a, b, c, d, e}, i_ :> Style[i, Bold]]
Out[29]=

Conversely, MapAtPart has access to the element values, but not their part specifications:

In[30]:=
ResourceFunction["MapAtPart"][All -> (Style[#, Bold] &)][ {a, b, c, d,
   e}]
Out[30]=

To have access to both indices and element, one needs to use intermediate assignment:

In[31]:=
With[
 {expr = {a, b, c, d, e}},
 ReplacePart[expr, i_ :> {Style[expr[[i]], Bold], i}]
 ]
Out[31]=

MapAtPart statements can be longer than ReplaceAll statements:

In[32]:=
list = {4, 5, 3, 2, 1}
Out[32]=
In[33]:=
ReplaceAll[list, {odd_?OddQ :> Echo[odd, "Odd Number"], even_?EvenQ :> Echo[even, "Even Number"]}]
Out[33]=
In[34]:=
ResourceFunction[
 "MapAtPart"][{Position[list, _?OddQ] -> EchoLabel["Odd Number"], Position[list, _?EvenQ] -> EchoLabel["Even Number"]}, list]
Out[34]=

The resource function SetComplementMap uses explicit positions for the first function:

In[35]:=
positions = {1, 5, 7, 8, 10};
makeBlue = Style[#, Blue] &;
makeRed = Style[#, Red] &;
In[36]:=
ResourceFunction["SetComplementMap"][makeRed, makeBlue, Range[10], positions]
Out[36]=

MapAtPart uses explicit positions for all functions:

In[37]:=
pos1 = List /@ positions
Out[37]=
In[38]:=
pos2 = List /@ Complement[Range[10], positions]
Out[38]=
In[39]:=
styleOp = ResourceFunction["MapAtPart"][{pos1 -> makeRed, pos2 -> makeBlue}]
Out[39]=
In[40]:=
styleOp[Range[10]]
Out[40]=

Possible Issues (7) 

Functions are applied to individual elements not sublists:

In[41]:=
partness = {1 ;; 4 -> f, 3 ;; -> g};
ResourceFunction["MapAtPart"][partness, a[5, 4, 3, {2, 1}, 0]]
Out[42]=

A Function specified with shorthand (#&) should be wrapped in parentheses:

In[43]:=
ResourceFunction["MapAtPart"][{1 -> g[#] &}, {a, b, c}]
Out[43]=
In[44]:=
ResourceFunction["MapAtPart"][{1 -> (g[#] &)}, {a, b, c}]
Out[44]=

A list of integers is considered a part path:

In[45]:=
ResourceFunction["MapAtPart"][{{2, 4} -> (Style[#, Red] &)}, Outer[{#1, #2} &, Range[5], Range[5]]]
Out[45]=

If each integer is meant as an index on the same level then either wrap them in a list, or use Span:

In[46]:=
ResourceFunction["MapAtPart"][{{{2}, {4}} -> (Style[#, Red] &)}, Outer[{#1, #2} &, Range[5], Range[5]]]
Out[46]=
In[47]:=
ResourceFunction["MapAtPart"][{2 ;; 4 ;; 2 -> (Style[#, Red] &)}, Outer[{#1, #2} &, Range[5], Range[5]]]
Out[47]=

When specifying an operator form, remember to wrap the function specification in a list. Notice below that Allg is applied to the second argument 2f:

In[48]:=
ResourceFunction["MapAtPart"][All -> g, 2 -> f]
Out[48]=

Wrap the specification in List to get an operator form:

In[49]:=
op = ResourceFunction["MapAtPart"][{All -> g, 2 -> f}]
Out[49]=
In[50]:=
op[{1, 2}]
Out[50]=

If a preceding function changes the expression's structure, then subsequent functions won't work as expected (especially if the positions in the expression no longer exist):

In[51]:=
removeEven = Replace[_?EvenQ -> Nothing];
styleGreen = Style[#, Green] &;
modifyStructure = {1 ;; 4 -> removeEven, 3 ;; -> styleGreen};
In[52]:=
ResourceFunction["MapAtPart"][modifyStructure, {2, 2, {2, 1}, 0}]
Out[52]=

Beware of symbol precedence. For example, an inner Style has precedence over an outer Style, so parts 3 and 4 below are Red instead of Green:

In[53]:=
red = Style[#, Red] &;
green = Style[#, Green] &;
color = {1 ;; 4 -> red, 3 ;; -> green};
In[54]:=
res = ResourceFunction["MapAtPart"][color, a[5, 4, 3, {2, 1}, 0]]
Out[54]=
In[55]:=
res // FullForm
Out[55]=

Framed, however, shows all styles:

In[56]:=
redFrame = Function[
   Framed[#, Background -> Black, BaseStyle -> {White}, FrameStyle -> Directive[Red, Thick]]];
greenFrame = Function[
   Framed[#, Background -> Blue, BaseStyle -> {White}, FrameStyle -> Directive[Green, Thick]]];
framing = {1 ;; 4 -> redFrame, 3 ;; -> greenFrame};
In[57]:=
ResourceFunction["MapAtPart"][framing, a[5, 4, 3, {2, 1}, 0]]
Out[57]=

Expressions with a Depth <= 1 will return a Failure:

In[58]:=
ResourceFunction["MapAtPart"][{Most -> f, Last -> g}, 1]
Out[58]=

Publisher

Faizon Zaman

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.0 – 15 December 2023

Related Resources

License Information