9
$\begingroup$

Is it possible to refer to the next element of the list when I'm using Map or should I always use For in this case?
For example I can write:

(1 + #1) & /@ {a, b, c, d}

but I can not write:

(1 + #1 + #2) & /@ {a, b, c, d}

The problem with the last element should be also avoided. So in last example I would like to get something like

{ 1 + a + b, 1 + b + c, 1 + c + d, 1 + d}
$\endgroup$
2
  • 2
    $\begingroup$ It is possible if you use MapIndexed. Also, #2 refers to the second argument of a function, not the second element of a list (or the next). $\endgroup$
    – rm -rf
    Oct 22 '13 at 7:42
  • 3
    $\begingroup$ I tend to use Partition in these situations, like (1 + #1 + #2) & @@@ Partition[{a, b, c, d}, 2, 1] or MapThread[(1 + #1 + #2) &, Transpose@Partition[{a, b, c, d}, 2, 1]]. I hope somebody will show a smarter way here... $\endgroup$ Oct 22 '13 at 7:49
5
$\begingroup$

One can use MapIndexed to access the next (or previous or any arbitrary offset) element of the currently mapped element. However, you also need to make checks so that you don't index it beyond its bounds. For example:

With[{list = Range@5}, MapIndexed[{f@#, f@list[[Mod[#2[[1]] + 1, Length@list, 1]]]} &, list]]
(* {{f[1], f[2]}, {f[2], f[3]}, {f[3], f[4]}, {f[4], f[5]}, {f[5], f[1]}} *)

Here, I've chosen to wrap the index back to the first element, but you can choose something else.

As Pinguin Dirk mentioned, Partition is also an option if your offsets are regular:

With[{list = Range@5}, {f@#, f@#2} & @@@ Partition[list, 2, 1, {1, 1}]]

Use the higher arguments of Partition to control how the endpoints/padding should be done.

$\endgroup$
4
$\begingroup$

One way to do this is as follows:

Map[Total[#] &, Partition[{a, b, c, d}, 2, 1]] + 1

the result is

(* {1 + a + b, 1 + b + c, 1 + c + d}   *)

Alternatively it can be written down in the pure function notations:

(1 + (#[[1]] + #[[2]]) &) /@ Partition[{a, b, c, d}, 2, 1]

The result is the same.

$\endgroup$
4
  • 2
    $\begingroup$ Or 1 + #1 + #2 & @@@ Partition[{a, b, c, d}, 2, 1] $\endgroup$ Oct 22 '13 at 8:07
  • $\begingroup$ @ChrisDegnen: pretty much my comment above :) $\endgroup$ Oct 22 '13 at 8:12
  • $\begingroup$ @Pinguin Dirk Yes, it is the same as in your comment. I apologize to have skipped reading the comments and turned to answer at the spot. $\endgroup$ Oct 22 '13 at 11:35
  • $\begingroup$ @AlexeiBoulbitch: no problem at all! I am glad I wasn't the only one with that idea (see the last sentence in my comment) :) all good! $\endgroup$ Oct 22 '13 at 11:38
4
$\begingroup$

To achieve the result: {1+a+b,1+b+c,1+c+d,1+d} [noting (1 + (#[[1]] + #[[2]]) &) /@ Partition[{a, b, c, d}, 2, 1] -> {1 + a + b, 1 + b + c, 1 + c + d}] you could simply do:

list={a,b,c,d};
1+list+PadRight[Rest@list,4]

and adapt for arbitrary list

$\endgroup$
1
  • 3
    $\begingroup$ Alternatively 1 + list + PadLeft[list, 4, 0, 1] $\endgroup$ Oct 22 '13 at 8:56
3
$\begingroup$

Use Partition to produce {{a, b}, {b, c}, {c, d}, {d}} then for the operation in your example total the sublists at the second level and + 1:

1 + Total[Partition[{a, b, c, d}, 2, 1, {1, 1}, {}], {2}]

Note the partitioning here differs from the other comments and answers which aren't delivering the answer you requested {1+a+b,1+b+c,1+c+d,1+d} as far as I can tell.

More generally you would do:

f @@@ Partition[{a, b, c, d}, 2, 1, {1, 1}, {}]

In your example f would be (1 + #1 + ##2) &

$\endgroup$
2
$\begingroup$

Another possibility is to use NestList and carry the current index so you can manipulate it or control it.

list = {a, b, c, d} ;
f[x_, y_] = 1 + x + y ;

NestList[
 {#[[1]]+1, f[list[[#[[1]]+1]], If[#[[1]]+1+1 <= Length[list], list[[#[[1]]+1+1]], 0]]} &,    
   {1, f[list[[1]], list[[2]]]}, Length[list]-1][[All,2]]
$\endgroup$

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .