使用JS、Lodash或Underscore合并包含嵌套对象数组的数组。

3

我正在尝试使用lodash javascript库合并这2个对象数组,但在合并过程中包含另一个数组的Subcategories属性未被合并。这是要合并的数组。

var menu1 = [
 {
    "PageName": "Designer",
    "Category": "Designer",
    "LinkTo": "/",
    "SubCategories": []
 },
 {
    "PageName": "CMS",
    "Category": "CMS",
    "LinkTo": "",
    "SubCategories": [
        {
            "Category": "Template DOP",
            "LinkTo": "/sendoutboundmessages"
        }
    ]
}];


var menu2 = [
 {
    "PageName": "CMS",
    "Category": "CMS",
    "LinkTo": "",
    "SubCategories": [
        {
            "Category": "Cataloghi",
            "LinkTo": "/catalogs-manager"
        }
    ]
 }
];

我正在尝试使用lodashJS的以下方法

 const merged = _(menu1) 
.keyBy('PageName')
.merge(_.keyBy(menu2, 'PageName')) 
.values() 
.value();

但它无法处理包含另一个数组的SubCategory属性。

当前的输出结果如下:

[
  {
    "PageName": "Designer",
    "Category": "Designer",
    "LinkTo": "/",
    "SubCategories": []
  },
  {
    "PageName": "CMS",
    "Category": "CMS",
    "LinkTo": "",
    "SubCategories": [
      {
        "Category": "Cataloghi",
        "LinkTo": "/catalogs-manager"
      }
    ]
  }
]

我希望您能提供以下输出:

[
  {
    "PageName": "Designer",
    "Category": "Designer",
    "LinkTo": "/",
    "SubCategories": []
  },
  {
    "PageName": "CMS",
    "Category": "CMS",
    "LinkTo": "",
    "SubCategories": [
      {
        "Category": "Cataloghi",
        "LinkTo": "/catalogs-manager"
      },
      {
        "Category": "Template DOP",
        "LinkTo": "/sendoutboundmessages"
      }
    ]
  }
]

感谢您的帮助。

1
SubCategories属性正在合并,但您需要2个SubCategories数组的联合。根据Lodash文档,“数组和普通对象属性递归合并”,“后续源覆盖先前源的属性分配”。 - Chris HG
1
好的,你是对的。有没有办法在不覆盖的情况下获取SubCategory的并集呢?我尝试了union方法,但输出结果不正确。谢谢。 - cesar andavisa
1
我在下面的回答中使用了union()和mergewith()的组合。 - Chris HG
2个回答

4

您可以使用LoDash的mergeWith。它与merge相同,但它接受自定义函数以使您对合并具有更多控制权。请尝试以下操作:

var menu1 = [
 {
    "PageName": "Designer",
    "Category": "Designer",
    "LinkTo": "/",
    "SubCategories": []
 },
 {
    "PageName": "CMS",
    "Category": "CMS",
    "LinkTo": "",
    "SubCategories": [
        {
            "Category": "Template DOP",
            "LinkTo": "/sendoutboundmessages"
        }
    ]
}];


var menu2 = [
 {
    "PageName": "CMS",
    "Category": "CMS",
    "LinkTo": "",
    "SubCategories": [
        {
            "Category": "Cataloghi",
            "LinkTo": "/catalogs-manager"
        }
    ]
 }
];

function customizer(objValue, srcValue, propertyName) {
 if (propertyName == 'SubCategories') {
   return _.union(srcValue,objValue);
 }
}

const merged = _(menu1) 
.keyBy('PageName')
.mergeWith(_.keyBy(menu2, 'PageName'), customizer) 
.values() 
.value();

console.log('merged', merged);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>


好的解决方案,自定义方法在合并过程中提供更多控制。谢谢。 - cesar andavisa

1

仅使用Javascript,使用mapfind方法

var menu1 = [
  {
    PageName: "Designer",
    Category: "Designer",
    LinkTo: "/",
    SubCategories: []
  },
  {
    PageName: "CMS",
    Category: "CMS",
    LinkTo: "",
    SubCategories: [
      {
        Category: "Template DOP",
        LinkTo: "/sendoutboundmessages"
      }
    ]
  }
];

var menu2 = [
  {
    PageName: "CMS",
    Category: "CMS",
    LinkTo: "",
    SubCategories: [
      {
        Category: "Cataloghi",
        LinkTo: "/catalogs-manager"
      }
    ]
  },
  {
    PageName: "Devloper",
    Category: "Devloper",
    LinkTo: "/",
    SubCategories: []
  }
];

const doMerge = (data1, data2, key_name) => {
  const merged = data1.map(item => {
    const obj = data2.find(x => x[key_name] === item[key_name]);
    const res = { ...item };
    if (obj) {
      for (const [key, value] of Object.entries(obj)) {
        if (value instanceof Array) {
          res[key] = [...res[key], ...value];
        } else {
          res[key] = value;
        }
      }
    }
    return res;
  });
  const keys = merged.map(x => x[key_name]);
  const other_items = data2.filter(x => !keys.includes(x[key_name]));
  return [...merged, ...other_items];
};

console.log(doMerge(menu1, menu2, "PageName"));


我尝试了这个,它可以正常工作,但是如果我添加一个在另一个数组中不存在的新PageName,它就不会合并。 - cesar andavisa
@cesarandavisa,我看到你提到的情况了...只有在menu2中缺少这些项目。我更新了答案,修复了这种情况。如果您仍然遇到任何问题,请告诉我。谢谢。 - Siva K V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接