# Merging pairs of a list with keeping the first elements and adding the second elements

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!

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


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


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

• This idea comes from pythonres = defaultdict(int);for i, j in li: res[i] += j print(res.items()) Jan 1, 2021 at 16:13