|
55 | 55 | from_keys/2, |
56 | 56 | map/2, |
57 | 57 | merge/2, |
| 58 | + merge_with/3, |
58 | 59 | remove/2, |
59 | 60 | update/3 |
60 | 61 | ]). |
@@ -439,6 +440,28 @@ merge(Map1, _Map2) when not is_map(Map1) -> |
439 | 440 | merge(_Map1, Map2) when not is_map(Map2) -> |
440 | 441 | error({badmap, Map2}). |
441 | 442 |
|
| 443 | +%%----------------------------------------------------------------------------- |
| 444 | +%% @param Combiner a function to merge values from Map1 and Map2 if a key exists in both maps |
| 445 | +%% @param Map1 a map |
| 446 | +%% @param Map2 a map |
| 447 | +%% @returns the result of merging entries from `Map1' and `Map2'. |
| 448 | +%% @doc Merge two maps to yield a new map. |
| 449 | +%% |
| 450 | +%% If `Map1' and `Map2' contain the same key, then the value from `Combiner(Key, Value1, Value2)' will be used. |
| 451 | +%% |
| 452 | +%% This function raises a `badmap' error if neither `Map1' nor `Map2' is a map. |
| 453 | +%% @end |
| 454 | +%%----------------------------------------------------------------------------- |
| 455 | +-spec merge_with( |
| 456 | + Combiner :: fun((Key, Value, Value) -> Value), Map1 :: #{Key => Value}, Map2 :: #{Key => Value} |
| 457 | +) -> #{Key => Value}. |
| 458 | +merge_with(Combiner, Map1, Map2) when is_map(Map1) andalso is_map(Map2) -> |
| 459 | + iterate_merge_with(Combiner, maps:next(maps:iterator(Map1)), Map2); |
| 460 | +merge_with(_Combiner, Map1, _Map2) when not is_map(Map1) -> |
| 461 | + error({badmap, Map1}); |
| 462 | +merge_with(_Combiner, _Map1, Map2) when not is_map(Map2) -> |
| 463 | + error({badmap, Map2}). |
| 464 | + |
442 | 465 | %%----------------------------------------------------------------------------- |
443 | 466 | %% @param Key the key to remove |
444 | 467 | %% @param MapOrIterator the map or map iterator from which to remove the key |
@@ -545,6 +568,19 @@ iterate_map(Fun, {Key, Value, Iterator}, Accum) -> |
545 | 568 | NewAccum = Accum#{Key => Fun(Key, Value)}, |
546 | 569 | iterate_map(Fun, maps:next(Iterator), NewAccum). |
547 | 570 |
|
| 571 | +%% @private |
| 572 | +iterate_merge_with(_Combiner, none, Accum) -> |
| 573 | + Accum; |
| 574 | +iterate_merge_with(Combiner, {Key, Value1, Iterator}, Accum) -> |
| 575 | + case Accum of |
| 576 | + #{Key := Value2} -> |
| 577 | + iterate_merge_with(Combiner, maps:next(Iterator), Accum#{ |
| 578 | + Key := Combiner(Key, Value1, Value2) |
| 579 | + }); |
| 580 | + #{} -> |
| 581 | + iterate_merge_with(Combiner, maps:next(Iterator), Accum#{Key => Value1}) |
| 582 | + end. |
| 583 | + |
548 | 584 | %% @private |
549 | 585 | iterate_merge(none, Accum) -> |
550 | 586 | Accum; |
|
0 commit comments