nix 函数以递归方式合并属性/记录并连接数组
nix function to merge attributes / records recursively and concatenate arrays
有人知道合并记录列表的函数吗
- 如果要合并的所有值都是记录 - 递归合并它们
- 如果要合并的所有值都是数组 - 连接数组
- 如果无法合并值 - 后一个值是首选
示例 1:
recursiveMergeAttrs [
{ a = "x"; c = "m"; list = [1]; }
{ a = "y"; b = "z"; list = [2]; }
]
returns
{ a = "y"; b = "z"; c="m"; list = [1 2] }
示例 2
recursiveMergeAttrs [
{
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
}
{
boot.loader.grub.device = "";
}
]
returns
{
boot.loader.grub.enable = true;
boot.loader.grub.device = "";
}
P.S.
递归更新不工作
recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets
recursiveMergeAttrs [ { a = "x"; c = "m"; list = [1]; } { a = "y"; b = "z"; list = [2]; } ]
returns
{ a = "y"; b = "z"; c = "m"; list = [ 2 ]; }
做到了吗
{ lib, ... }:
with lib;
/*
Merges list of records, concatenates arrays, if two values can't be merged - the latter is preferred
Example 1:
recursiveMerge [
{ a = "x"; c = "m"; list = [1]; }
{ a = "y"; b = "z"; list = [2]; }
]
returns
{ a = "y"; b = "z"; c="m"; list = [1 2] }
Example 2:
recursiveMerge [
{
a.a = [1];
a.b = 1;
a.c = [1 1];
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
}
{
a.a = [2];
a.b = 2;
a.c = [1 2];
boot.loader.grub.device = "";
}
]
returns
{
a = {
a = [ 1 2 ];
b = 2;
c = [ 1 2 ];
};
boot = {
loader = {
grub = {
device = "";
enable = true;
};
};
};
}
*/
let
recursiveMerge = attrList:
let f = attrPath:
zipAttrsWith (n: values:
if tail values == []
then head values
else if all isList values
then unique (concatLists values)
else if all isAttrs values
then f (attrPath ++ [n]) values
else last values
);
in f [] attrList;
in
recursiveMerge
有人知道合并记录列表的函数吗
- 如果要合并的所有值都是记录 - 递归合并它们
- 如果要合并的所有值都是数组 - 连接数组
- 如果无法合并值 - 后一个值是首选
示例 1:
recursiveMergeAttrs [
{ a = "x"; c = "m"; list = [1]; }
{ a = "y"; b = "z"; list = [2]; }
]
returns
{ a = "y"; b = "z"; c="m"; list = [1 2] }
示例 2
recursiveMergeAttrs [
{
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
}
{
boot.loader.grub.device = "";
}
]
returns
{
boot.loader.grub.enable = true;
boot.loader.grub.device = "";
}
P.S.
递归更新不工作
recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets
recursiveMergeAttrs [ { a = "x"; c = "m"; list = [1]; } { a = "y"; b = "z"; list = [2]; } ]
returns
{ a = "y"; b = "z"; c = "m"; list = [ 2 ]; }
做到了吗
{ lib, ... }:
with lib;
/*
Merges list of records, concatenates arrays, if two values can't be merged - the latter is preferred
Example 1:
recursiveMerge [
{ a = "x"; c = "m"; list = [1]; }
{ a = "y"; b = "z"; list = [2]; }
]
returns
{ a = "y"; b = "z"; c="m"; list = [1 2] }
Example 2:
recursiveMerge [
{
a.a = [1];
a.b = 1;
a.c = [1 1];
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
}
{
a.a = [2];
a.b = 2;
a.c = [1 2];
boot.loader.grub.device = "";
}
]
returns
{
a = {
a = [ 1 2 ];
b = 2;
c = [ 1 2 ];
};
boot = {
loader = {
grub = {
device = "";
enable = true;
};
};
};
}
*/
let
recursiveMerge = attrList:
let f = attrPath:
zipAttrsWith (n: values:
if tail values == []
then head values
else if all isList values
then unique (concatLists values)
else if all isAttrs values
then f (attrPath ++ [n]) values
else last values
);
in f [] attrList;
in
recursiveMerge