3
$\begingroup$

I have a list that was generated by the below code:

Do[
 Do[
  AppendTo[list, {RandomInteger[i], RandomInteger[j]}, 
  {i, 1, 5}
 ], 
 {j, 1, 5}
]

A result can be produced as :

{{1, 2}, {2, 1}, {3, 0}, {2, 1}, {1, 1},
 {1, 0}, {1, 2}, {2, 2}, {4, 2}, {5, 0}, 
 {1, 0}, {1, 12}, {2, 0}, {4, 2}, {5, 3}, 
 {0, 4}, {2,4}, {0, 2}, {4, 1}, {3, 1},
 {1, 0}, {1, 0}, {2, 3}, {1, 1}, {3, 2}}

I wish to merge all pairs whose first elements are the same. Provided that the first element must be kept and the second elements must be accumulated. There is an answer here but I do not have the list at final end, and I have to access the result in any iteration

For example at the first I have

{1, 2}, {2, 1}, {3, 0}}

and after theses and for next iteration, I have to have:

{1, 2}, {2, 2}, {3, 0}}

and next iteration:

 {1, 3}, {2, 2}, {3, 0}}

and so on...I know that I can use Accumulate but I do not know where I must make use of them!

$\endgroup$

2 Answers 2

6
$\begingroup$
ClearAll[foldGroupBy]

foldGroupBy = FoldList[
     KeyValueMap[List][GroupBy[Append @ ##, First -> Last, Total]] &, 
    {First @ #}, Rest @ #] &;

foldGroupBy @lst // Column

Example:

lst = {{1, 2}, {2, 1}, {3, 0}, {2, 1}, {1, 1}, {1, 0}, {1, 2}, {2, 2}, {4, 2}, 
  {5, 0}, {1, 0}, {1, 12}, {2, 0}, {4, 2}, {5, 3}, {0, 4}, {2,4}, {0, 2}, {4, 1},
  {3, 1}, {1, 0}, {1, 0}, {2, 3}, {1, 1}, {3, 2}};

foldGroupBy @ lst // Column

enter image description here

Also:

ClearAll[mapGroupBy]
mapGroupBy[data_] := KeyValueMap[List][
  GroupBy[Take[data, #], First -> Last, Total]] & /@ Range[Length@data]

ClearAll[mapMerge]
mapMerge[data_] := KeyValueMap[List]@
    Merge[Total][Take[Association @* Rule @@@ data, #]] & /@ Range[Length @ data]

and based on Kuba's answer here

ClearAll[mapGatherBy] 
mapGatherBy[data_] := {#[[1, 1]], Total[#[[All, 2]]]} & /@ 
    GatherBy[Take[data, #], First] & /@ Range[Length @ data]

foldGroupBy@lst == mapMerge @ lst == mapGroupBy @ lst  == mapGatherBy @ lst
 True
$\endgroup$
1
$\begingroup$

A less tricky way:

res = Association[];
ans = Reap[
    Table[{i, j} = m;
    res[i] = Lookup[res, i, 0] + j;
    res // # /. Rule | Association :> List & // Sow, {m, lst}]
    ] // Flatten[#, 1] &;
ans // Drop[#, -1] & // Column
$\endgroup$
1
  • $\begingroup$ This idea comes from pythonres = defaultdict(int);for i, j in li: res[i] += j print(res.items()) $\endgroup$ Jan 1, 2021 at 16:13

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.