I have a list $(d_1, d_2, .. d_k)$ and I want to create all sums that I get for adding only two elements for my list $(d_1+d_2, d_1+d_3,...d_{k-1}+d_k)$. The RotateLeft
function gives me only some of my sums and I need all of them.
7 Answers
l = {a, b, c, d};
Plus @@@ Subsets[l, {2}]
(*
{a + b, a + c, a + d, b + c, b + d, c + d}
*)
edit
Some timings
Come downvote @Verde
l = {a, b, c, d}
l~Subsets~{2}~Total~{2}
-
-
1$\begingroup$ This one is six times faster than the
Plus @@@
solution, twice as fast as theOuter
solution, and three times faster than theTable
solution. $\endgroup$– whuberCommented Sep 4, 2012 at 12:50 -
$\begingroup$ And ten times slower than
Total /@ Subsets[l, {2}]
$\endgroup$ Commented Sep 4, 2012 at 13:39 -
2$\begingroup$ @whuber
l = RandomReal[1, 10^3]; {(Timing@(l~Subsets~{2}~Total~{2}))[[1]], (Timing[ Plus @@@ Subsets[l, {2}]])[[1]]}
-> {2.89, 0.547} ... $\endgroup$ Commented Sep 4, 2012 at 13:43 -
$\begingroup$ @Verde You're right: that's astounding, given how similar the
Total /@
and~Total~2
constructs are!. $\endgroup$– whuberCommented Sep 4, 2012 at 14:34
l = {a, b, c, d};
Let's make use of pattern matching ( even though there are faster methods especially for list manipulations) :
ReplaceList[ l, {___, x_, ___, y_, ___} -> x + y]
{a + b, a + c, a + d, b + c, b + d, c + d}
Typically, efficiency of pattern matching solutions is worse than that of functional approach, nevertheless we point out a remarkable feature of the result of ReplaceList
: it is identical with other (functional) methods, e.g. (taking a longer list) we have:
ls = {a, b, c, d, e, f, g, h, i, j, k, l, , m, n, o, p, q, r, s};
ReplaceList[ls, {___, x_, ___, y_, ___} -> x + y] ==
Plus @@@ Subsets[ls, {2}] == ls~Subsets~{2}~Total~{2}
True
Just to show that there's more than one way to do things in Mathematica:
test = {a, b, c, d, e};
Total /@ (Join @@ MapIndexed[Drop[#1, First[#2]] &,
Outer[List, test, test]])
{a + b, a + c, a + d, a + e, b + c, b + d, b + e, c + d, c + e, d + e}
Of course, Oleksandr's and Verde's suggestions are the more compact way of going about it.
Something like :
data = {a, b, c, d};
Flatten[Table[data[[i]] + data[[j]], {i, 1, Length[data] - 1}, {j, i + 1, Length[data]}],1]
(* {a + b, a + c, a + d, b + c, b + d, c + d} *)
Alternatively (plus suggestion from @Oleksandr R.) :
Total /@ Subsets[data, {2}]
And just because RotateLeft
was mentioned :
Union[Flatten[Total /@ Subsets[NestList[RotateLeft[#] &, data, Length[data] - 1], {2}], 1]]
-
$\begingroup$ The third one seems a memory hog :) $\endgroup$ Commented Sep 4, 2012 at 14:52
Since somebody mentioned timings...
Module[{x = Outer[Plus, l, l]},
Flatten[x[[#, # + 1 ;;]] & /@ Range[Length@x - 1]]]
Subsets[Plus @@ l, {2}]
(* or Subsets[Total@l, {2}] *)
{a + b, a + c, a + d, b + c, b + d, c + d}