So I have a function f[x : {{_, _} ...}] := f /@ x; f[a_,b_]=:a+b
. I can input f[{1,2},{2,0},{3,4}]
and get {3,2,7}
. However, I want the function to also sort out the answers so I get {{2,2},{1,3},{3,7}}
, where the first value corresponds to the position of ordered pair in the input. I have no idea how to approach this. I attempted to use Sort but an error message pops up. Are there other commands that would achieve this? Thanks, I'm new to using Mathematica and any help would be appreciated!!
4 Answers
You can get the row sums using {2}
as the second argument of Total
:
Total[{{1, 2}, {2, 0}, {3, 4}}, {2}]
{3, 2, 7}
Then you can use Ordering
and Sort
to get the ordering of sums and the sorted sums, respectively:
Through @ {Ordering, Sort} @ %
{{2, 1, 3}, {2, 3, 7}}
and Transpose
the resulting pair of lists:
Transpose @ %
{{2, 2}, {1, 3}, {3, 7}}
Combine the three steps to define a function:
ClearAll[indexedSortedSum]
indexedSortedSum = Transpose[Through@{Ordering, Sort}@Total[#, {2}]] &;
indexedSortedSum @ {{1, 2}, {2, 0}, {3, 4}}
{{2, 2}, {1, 3}, {3, 7}}
Alternatively, you can Apply
Plus
at Level
1
instead if using Total
ClearAll[indexedSortedSum2]
indexedSortedSum2 = Transpose[Through@{Ordering, Sort}[Plus @@@ #]] &;
indexedSortedSum2 @ {{1, 2}, {2, 0}, {3, 4}}
{{2, 2}, {1, 3}, {3, 7}}
MapIndexed
work fine.
list = {{1, 2}, {2, 0}, {3, 4}};
result=SortBy[First]@MapIndexed[{Total@#1, #2} &][list]
(* {{2, {2}}, {3, {1}}, {7, {3}}} *)
and then adjust the appearance.
Flatten[#, 1] & /@ Reverse /@result
(* {{2, 2}, {1, 3}, {3, 7}} *)
Are you sure you have typed your function as you intended? I can't make it work, so I think you mean:
f[x : {{_, _} ...}] := f /@ x;
f[{a_, b_}] := a + b;
f[{{1, 2}, {2, 0}, {3, 4}}]
Which outputs
{3,2,7}
You could also use (amongst many other possibilities):
{{1, 2}, {2, 0}, {3, 4}} /. {x_, y_} -> x + y
I think from your example output {{2,2},{1,3},{3,7}}
that you want to sort in ascending order of the answers, not the input tuples (but the Code Golfers will be much slicker):
list1 = {{1, 2}, {2, 0}, {3, 4}};
addByPosition[x_List] := x[[#]] /. x[[#]] -> {#, x[[#]][[1]] + x[[#]][[2]]} & /@ Range[Length[x]]
SortBy[Last][addByPosition[list1]]
(* {{2,2}, {1,3}, {3,7}} *)
f[list_] := (
k = 1;
Sort[Map[{k++, #[[1]] + #[[2]]} &, list], #1[[2]] < #2[[2]] &]
)
f[{{1, 2}, {2, 0}, {3, 4}}]
(* Result of calling f *)
(* {{2, 2}, {1, 3}, {3, 7}} *)
-
$\begingroup$ Amazing to see how the different methods proposed on this page can achieve the same result. I did some Timing. This one gives me 0.000032 second. Others, up to now, vary between 0.000038 and 0.000048. $\endgroup$ Commented Oct 5, 2020 at 20:10
-
$\begingroup$ Using (abusing?) the fact that the first term in each tuple is the position, how about this (0.000034)?
SortBy[Last][ ReplaceList[{{1, 2}, {2, 0}, {3, 4}}, {___, {x_, y_}, ___} -> {x, x + y}]]
$\endgroup$– pudepiedCommented Oct 7, 2020 at 16:07