1
$\begingroup$

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

$\endgroup$

4 Answers 4

2
$\begingroup$

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}}
$\endgroup$
1
$\begingroup$

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}} *)
$\endgroup$
1
$\begingroup$

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}} *)
$\endgroup$
1
$\begingroup$
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}} *)
$\endgroup$
2
  • $\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$
    – pudepied
    Commented Oct 7, 2020 at 16:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.