6
$\begingroup$

I have a list of the form,

mylist = {{0.1, 1.2},{0.3, 2.1},{0.1, 0.5},{0.4, 0.4},{0.4, 0.1},{0.1, 1.6}}

I would like to create a function, myfn, that takes a list and outputs a new list where the sublists with the same first element are combined, by adding the second elements together. For example in the above, I expect the output:

myfn[mylist]
(* Out: {{0.1, 3.3}, {0.3, 2.1}, {0.4, 0.5}} *)

I have the following piece of code that does the job, but it looks not particularly elegant and I was wondering if there are better ways to achieve this result?:

myfn[list_] := Module[{listnew = {list[[1]]}, pos},
Do[
  Which[
    Length@Position[First@Transpose[listnew], list[[i, 1]]] == 0,
    listnew = Join[listnew, {list[[i]]}],

    Length@Position[First@Transpose[listnew], list[[i, 1]]] == 1,
    pos = Flatten@Position[listnew, list[[i, 1]]];
    listnew[[pos[[1]], 2]] +=  list[[i, 2]],

    True,
    Print["Never get here in myfn. Aborting now..."]; Abort[]
    ]
, {i, 2, Length[list]}];
listnew
]
$\endgroup$

5 Answers 5

6
$\begingroup$

Use GatherBy to collect members the list by their first elements, then total the second elements.

mylist = {{0.1, 1.2},{0.3, 2.1},{0.1, 0.5},{0.4, 0.4},{0.4, 0.1},{0.1, 1.6}};

{#[[1, 1]], Total[#[[All, 2]]]} &/@ GatherBy[mylist, First]
(* {{0.1, 3.3}, {0.3, 2.1}, {0.4, 0.5}} *)
$\endgroup$
6
$\begingroup$
Clear["Global`*"]
mylist = {{0.1, 1.2}, {0.3, 2.1}, {0.1, 0.5}, {0.4, 0.4}, {0.4, 
   0.1}, {0.1, 1.6}}

GroupBy[mylist, First -> Last, Total] // KeyValueMap[List]

{{0.1, 3.3}, {0.3, 2.1}, {0.4, 0.5}}

$\endgroup$
5
$\begingroup$

An easy way to get an equivalent representation to what you desire is:

Total /@ GroupBy[mylist, First -> Last]
(* <|0.1 -> 3.3, 0.3 -> 2.1, 0.4 -> 0.5|> *)

You can transform this to your exact expected result:

KeyValueMap[List, Total /@ GroupBy[mylist, First -> Last]]
(* {{0.1, 3.3}, {0.3, 2.1}, {0.4, 0.5}} *)
$\endgroup$
5
$\begingroup$

One way to do it:

List @@@ (Merge[Rule @@@ mylist, Total] // Normal)
$\endgroup$
5
$\begingroup$

A variant of bmf's answer using MapApply (new in 13.1)

KeyValueMap[List] @ Merge[Total] @ MapApply[Rule] @ list

{{0.1, 3.3}, {0.3, 2.1}, {0.4, 0.5}}

A hash-free variant of creidhne's answer using Query

Query[All, {1 -> First, 2 -> Total}] @ Map[Transpose] @ GatherBy[list, First]

{{0.1, 3.3}, {0.3, 2.1}, {0.4, 0.5}}

$\endgroup$

Your Answer

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

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