# Subtracting from a specific column

I have a huge list with huge sublists of the form

list={{a,b,c,d},{e,f,g,h},{i,j,k,l}}


I am looking for a way to manipulate these sublists based on the positions of the elements. Something like

list/.{j_,k_,l_,m_}->{j-1,k,l,m}


but without having to write the whole pattern. Is there any way to specify such manipulation based on the position of the element? Something like

list/.#[[1]] & -> #[[1]] - 1 &


that would work?

• Do you want (for example) to subtract one from the first element in each sublist? Commented Feb 17, 2014 at 18:56
• Are the sublists all of the same length? Commented Feb 17, 2014 at 18:58
• f[l_List] := {First@l - 1, Sequence @@ Rest@l}; f /@ list ? Commented Feb 17, 2014 at 18:59
• MapAt[# - 1 &, list, {All, 1}] or {#1 - 1, ##2} & @@@ list. Commented Feb 17, 2014 at 19:01
• Could you guys please post these as answers? Although they are somewhat redundant (given that they all should solve the problem), it is nice to see for others to see the various possibilities to solve this
– Sos
Commented Feb 17, 2014 at 19:08

You could use: MapAt:

MapAt[ # - 1 &, list, {All, 1}]

{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}


or Apply at the first level (shorthand @@@) (see also SlotSequence, shorthand ##n):

{#1 - 1, ##2}& @@@ list

• Your first answer, together with @andre's answer, seems to be the most robust since I can specify the position to to the subtraction, without having to do it only in the 1st position.
– Sos
Commented Feb 18, 2014 at 16:30

This is quite neat:

list[[;; , 1]]--

• It yields {a, e, i} for the list in the OP so one has to evaluate list twice to get the result of list /. {j_, k_, l_, m_} -> {j - 1, k, l, m}, since it changes list I find it's rather a drawback. Commented Feb 18, 2014 at 10:30
• @Artes Indeed. Well, after this list is updated, the method you want to use depends of what OP needs at the end.
– Kuba
Commented Feb 18, 2014 at 10:33

If you write

list[[All, 1]] = list[[All, 1]] - 1


list will be updated with the new values of the first element of each sublist.

Maybe

ReplacePart[list, (x : {_, 1}) :> (Extract[list, x] - 1)]


?

The positions of the elements are specified by the pattern on the indices : {_,1}

{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

You might be able to use this rule-based method

Replace[list, {f_, r___} -> {f - 1, r}, {1}]

{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}


or something similar. This will work for any sublist length.

list2 = {{a, b, c, d}, {e, f, g}, {h}};
Replace[list2, {f_, r___} -> {f - 1, r}, {1}]

{{-1 + a, b, c, d}, {-1 + e, f, g}, {-1 + h}}


More generally

munge[func_, data_] := Replace[data, {f_, r___} :> {func@f, r}, {1}]
munge[# - 1 &, list]

{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

• I had been trying to play with replacement rules but to no avail, but now I see why. Btw, would there be a way to specify the position in which the replacement would have to be made? e.g. if I wanted to apply the rule to each element in position 37 of sublists with 100 elements?
– Sos
Commented Feb 18, 2014 at 16:26
• Nevermind, I guess that would have to be something similar to what @andre answered
– Sos
Commented Feb 18, 2014 at 16:28

That's a prime example to use Threaded which was introduced in v13.1

list = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}};
list + Threaded[{-1, 0, 0, 0}]


{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

• +1 - That's probably the nicest solution
– eldo
Commented Dec 20, 2023 at 23:50
• @eldo Thanks a lot :-)
– bmf
Commented Dec 20, 2023 at 23:53
• (+1 ) I agree with @eldo, it seems like the nicest solution to me. :-) Commented Dec 20, 2023 at 23:56
• @E.Chan-López thanks a lot mate :-)
– bmf
Commented Dec 21, 2023 at 0:02
list = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}};


We can also use ReplaceAt (new in 13.1)

ReplaceAt[x_ :> x - 1, {All, 1}] @ list


{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

ReplaceAt[x_ /; x =!= e :> x - 1, {All, 1}] @ list


{{-1 + a, b, c, d}, {e, f, g, h}, {-1 + i, j, k, l}}

To update list inline we can employ ApplyTo (new in 12.2)

list //= ReplaceAt[x_ :> x - 1, {All, 1}];

list


{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

Using Cases:

list = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}};

Cases[list, x_ :> {-1 + First@x, Sequence @@ Rest@x}]

(*{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}*)


Edit Or as @eldo suggests, an equivalent way of doing it using Splice instead of Sequence:

Cases[list, x_ :> {-1 + First@x, Splice@Rest@x}] (*Thanks, eldo!*)

(*{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}*)

• Very nice, +1, you could also use Splice@ instead of Sequence@@
– eldo
Commented Dec 20, 2023 at 17:20
list + ConstantArray[{-1,0,0,0},3]

(* {{-1+a,b,c,d},{-1+e,f,g,h},{-1+i,j,k,l}} *)

• That's, also, very slick!
– bmf
Commented Dec 21, 2023 at 9:53

Using SubetMap:

Clear["Global*"];
list = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}};
SubsetMap[# - 1 &, list, {All, 1}] // Column


Result:

list = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}};


1.

A shorter Cases - variant

Cases[{a_, b__} :> {a - 1, b}] @ list


{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

2.

Using Query

Query[All, {#[[1]] - 1 &, Splice @* Rest}] @ list


{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}

• (+1) Also Query[All, {1 -> (# - 1 &)}]@list (after Sjoerd Smit) Commented Jun 27 at 19:48
• Thanks, 1066, your suggestion is nicer and more appropriate in this case.
– eldo
Commented Jun 27 at 22:14
list = {{a, b, c, d}, {e, f, g, h}, {i, j, k, l}};


A variant of @andre314's answer with ReplacePart using Part instead of Extract is the following:

ReplacePart[#, {m_, 1} :> #[[m, 1]] - 1] &@list


{{-1 + a, b, c, d}, {-1 + e, f, g, h}, {-1 + i, j, k, l}}`