diff --git a/pkgs/lib/attrsets.nix b/pkgs/lib/attrsets.nix index de6eccbec1f..63448847a15 100644 --- a/pkgs/lib/attrsets.nix +++ b/pkgs/lib/attrsets.nix @@ -5,7 +5,8 @@ with { inherit (import ./trivial.nix) or; inherit (import ./default.nix) fold; inherit (import ./strings.nix) concatStringsSep; - inherit (import ./lists.nix) concatMap concatLists; + inherit (import ./lists.nix) concatMap concatLists all; + inherit (import ./misc.nix) maybeAttr; }; rec { @@ -78,6 +79,16 @@ rec { filterAttrs = pred: set: listToAttrs (fold (n: ys: let v = getAttr n set; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (attrNames set)); + /* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list: + foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }] + => { a = [ 2 3 ]; } + */ + foldAttrs = op: nul: list_of_attrs: + fold (n: a: + fold (name: o: + o // (listToAttrs [{inherit name; value = op (getAttr name n) (maybeAttr name nul a); }]) + ) a (attrNames n) + ) {} list_of_attrs; /* Recursively collect sets that verify a given predicate named `pred' from the set `attrs'. The recursion is stopped when the predicate is diff --git a/pkgs/lib/tests.nix b/pkgs/lib/tests.nix index 835298ddb9e..04acb7632ea 100644 --- a/pkgs/lib/tests.nix +++ b/pkgs/lib/tests.nix @@ -58,6 +58,13 @@ runTests { ([ 1 2 3 ] == (take 4 [ 1 2 3 ])) ]; + testFoldAttrs = { + expr = foldAttrs (n: a: [n] ++ a) [] [ + { a = 2; b = 7; } + { a = 3; c = 8; } + ]; + expected = { a = [ 2 3 ]; b = [7]; c = [8];}; + }; testOverridableDelayableArgsTest = { expr =