3
$\begingroup$

I have an Association in which values are lists of lists containing an Integer and a DateObject. I would like to build a function that adds all Integers that have the same dates.

assoc = <| "first" -> {{1,DateObject[{2019,1}]},{2,DateObject[{2019,3}]},{3,DateObject[{2019,7}]},{4,DateObject[{2019,1}]}}, "Second" ->{{1,DateObject[{2019,1}]},{2,DateObject[{2019,8}]},{3,DateObject[{2019,7}]},{4,DateObject[{2019,8}]}}|>

I am looking for a function F for which: response = F/@assoc

Where respnse will result in: assoc = <| "first" -> {{5,DateObject[{2019,1}]},{2,DateObject[{2019,3}]},{3,DateObject[{2019,7}]}}, "Second" ->{{1,DateObject[{2019,1}]},{6,DateObject[{2019,8}]},{3,DateObject[{2019,7}]}}|>

Is there any clever pattern matching way to do this for the general case?

Thanks!

$\endgroup$
4
$\begingroup$

Update: "Adding values (...) through pattern matching":

You can use ReplaceRepeatedas follows:

rule = {a___, {b_, c_DateObject}, d___, {e_, c_}, f___} :> {a, {b + e, c}, d, f};

ReplaceRepeated[rule] /@ assoc

enter image description here

Original answer:

f1 = Map[Values @ GroupBy[#, Last, {Total[First /@ #], #[[1, 2]]} &] &];
f1 @ assoc

enter image description here

Also

f2 = Map[{Total[#[[All, 1]]], #[[1, 2]]} & /@ GatherBy[#, Last] &];

f2 @ assoc

same result

f3 = Map[{Total[#[[All, 1]]], #[[1, 2]]} & /@ SplitBy[#, Last] & @* SortBy[Last]];

f3 @assoc

enter image description here

Alternatively,

Dataset[assoc][All, GroupBy[Last], Total /* First]

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you @kglr, this does solve my issues. I was hoping I could find a way to do this with rules or pattern matching, but perhaps that is the wrong approach! $\endgroup$ – MathematicaUser Mar 17 at 14:10
  • $\begingroup$ @MathematicaUser, my pleasure. $\endgroup$ – kglr Mar 17 at 20:44
  • $\begingroup$ @MathematicaUser, please see the update re suing rules and pattern matching to get the same result. $\endgroup$ – kglr Mar 17 at 21:58
3
$\begingroup$

Here is a way that uses version 12.1's shiny new SubsetReplace:

SubsetReplace[x:{{_, d_} ..} :> {Total@x[[All, 1]], d}] /@ assoc

result screenshot

| improve this answer | |
$\endgroup$
2
$\begingroup$

You may use Query.

Query[All, GroupBy[Last -> First] /* KeyValueMap[Reverse[{##}] &], Total]@assoc

enter image description here

Hope this helps.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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