【问题标题】:nix function to merge attributes / records recursively and concatenate arraysnix 函数以递归方式合并属性/记录并连接数组
【发布时间】:2019-02-03 15:57:39
【问题描述】:

有人知道合并记录列表的功能吗

  • 如果要合并的所有值都是记录 - 递归合并它们
  • 如果要合并的所有值都是数组 - 连接数组
  • 如果无法合并值 - 首选后一个值

示例 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 = "";
}

附言

recursiveUpdate 不工作

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 ]; }

【问题讨论】:

    标签: nix


    【解决方案1】:

    做到了

    { 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
    

    【讨论】:

      猜你喜欢
      • 2019-05-08
      • 2018-02-26
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多