Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question
1  
Do you want (for example) to subtract one from the first element in each sublist? –  belisarius Feb 17 at 18:56
    
Are the sublists all of the same length? –  Szabolcs Feb 17 at 18:58
    
f[l_List] := {First@l - 1, Sequence @@ Rest@l}; f /@ list ? –  belisarius Feb 17 at 18:59
    
@belisarius Yes, for instance. @Szabolcs Yes, Length@myoriginallist outputs 81 for all –  Sosi Feb 17 at 18:59
2  
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 –  Sosi Feb 17 at 19:08

5 Answers 5

up vote 8 down vote accepted

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
share|improve this answer
    
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. –  Sosi Feb 18 at 16:30

This is quite neat:

list[[;; , 1]]--
share|improve this answer
2  
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. –  Artes Feb 18 at 10:30
1  
@Artes Indeed. Well, after this list is updated, the method you want to use depends of what OP needs at the end. –  Kuba Feb 18 at 10:33

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}}

share|improve this answer
1  
+1, pretty use of patterns. –  rasher Feb 18 at 10:53

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.

share|improve this answer

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}}
share|improve this answer
    
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? –  Sosi Feb 18 at 16:26
    
Nevermind, I guess that would have to be something similar to what @andre answered –  Sosi Feb 18 at 16:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.