【问题标题】:Map arrays using union or intersection to produce a third array使用并集或交集映射数组以生成第三个数组
【发布时间】:2023-03-18 10:36:01
【问题描述】:

我正在尝试解决 Angular 7 中的一个问题,我需要编写一个函数,该函数接受两个对象数组,在本例中为第一个对象和第二个对象,并返回第三个数组。

第三个数组和第一个数组非常相似,但是children数组中count键的值取决于第二个数组中是否有children或者如果存在,反映该值count 在该对象中。有没有 angular 的数组映射函数可以解决这个问题?

第一个数组:

[
    {
        "name": "Category 1",
        "value": "Vegetables",
        "children": [
            {"name": "Carrots", "value": "Carrots", "count": 2},
            {"name": "Peas", "value": "Peas", "count": 1}
        ]
    },
    {
        "name": "Category 2",
        "value": "Fruits",
        "children": [
            {"name": "Apples", "value": "Apples", "count": 10},
            {"name": "Bananas", "value": "Bananas", "count": 5}
        ]
    },
    {
        "name": "Category 3",
        "value": "Desserts",
        "children": [
            {"name": "Ice Cream", "value": "IceCream", "count": 3},
            {"name": "Cakes", "value": "Cakes", "count": 3}
        ]
    }
]

第二个数组

[
    {
        "name": "Category 1",
        "value": "Vegetables",
        "children": [
            {"name": "Peas", "value": "Peas", "count": 1}
        ]
    },
    {
        "name": "Category 2",
        "value": "Fruits",
        "children": [
            {"name": "Apples", "value": "Apples", "count": 3},
            {"name": "Bananas", "value": "Bananas", "count": 2}
        ]
    },
    {
        "name": "Category 3",
        "value": "Desserts",
        "children": []
    }
]

第三个数组

[
    {
        "name": "Category 1",
        "value": "Vegetables",
        "children": [
            {"name": "Carrots", "value": "Carrots", "count": 0},
            {"name": "Peas", "value": "Peas", "count": 1}
        ]
    },
    {
        "name": "Category 2",
        "value": "Fruits",
        "children": [
            {"name": "Apples", "value": "Apples", "count": 3},
            {"name": "Bananas", "value": "Bananas", "count": 2}
        ]
    },
    {
        "name": "Category 3",
        "value": "Desserts",
        "children": [
            {"name": "Ice Cream", "value": "IceCream", "count": 0},
            {"name": "Cakes", "value": "Cakes", "count": 0}
        ]
    }
]

【问题讨论】:

    标签: javascript arrays angular typescript object


    【解决方案1】:

    您可以非常简单地使用mapfind,然后使用reduce 数组。

    const arr1 = [{"name":"Category 1","value":"Vegetables","children":[{"name":"Carrots","value":"Carrots","count":2},{"name":"Peas","value":"Peas","count":1}]},{"name":"Category 2","value":"Fruits","children":[{"name":"Apples","value":"Apples","count":10},{"name":"Bananas","value":"Bananas","count":5}]},{"name":"Category 3","value":"Desserts","children":[{"name":"Ice Cream","value":"IceCream","count":3},{"name":"Cakes","value":"Cakes","count":3}]}];
    const arr2 = [{"name":"Category 1","value":"Vegetables","children":[{"name":"Peas","value":"Peas","count":1}]},{"name":"Category 2","value":"Fruits","children":[{"name":"Apples","value":"Apples","count":3},{"name":"Bananas","value":"Bananas","count":2}]},{"name":"Category 3","value":"Desserts","children":[]}];
    const res = arr1.map(({ name, value, children }) => {
      let found = arr2.find(({ name: n, value: v }) => n == name && v == value);
      if (found) children = children.concat(found.children).reduce((a, c) => {
        let f = a.findIndex(({ name: n }) => n == c.name);
        if (f > -1) a[f].count += c.count;
        else a.push(c);
        return a;
      }, []);
      return { name, value, children };
    });
    console.log(res);
    .as-console-wrapper { max-height: 100% !important; top: auto; }

    【讨论】:

    • 我认为这是在结果数组中添加重复的孩子,而不是更新 count 键的值。例如:您可以看到,在您的 sn-p 解决方案中,Category 1 的结果数组的 children 现在有 2 个对象,其中有 Peas,每个对象都有一个 count: 1,而不是有一个 count: 2
    • 修复了@Jake,好点了吗?
    • 对不起,现在没有重复,这很好,但是计数与帖子中的第三个数组不匹配。 :(
    • Erm...第一个阵列中的 3 个蛋糕和冰淇淋发生了什么事?他们为什么去?
    • 由于第二个数组,没有它们,它们应该在第三个数组中,但它们的计数应该是0。
    【解决方案2】:

    这里的想法是

    • 首先将第二个数组更改为对象,以便更容易在其上查找值
    • 现在循环遍历 array1 并从 array2 中获取相应的子节点
    • 循环数组 1 的子元素并根据数组 2 的子元素更改值

    const arr1 = [{"name":"Category 1","value":"Vegetables","children":[{"name":"Carrots","value":"Carrots","count":2},{"name":"Peas","value":"Peas","count":1}]},{"name":"Category 2","value":"Fruits","children":[{"name":"Apples","value":"Apples","count":10},{"name":"Bananas","value":"Bananas","count":5}]},{"name":"Category 3","value":"Desserts","children":[{"name":"Ice Cream","value":"IceCream","count":3},{"name":"Cakes","value":"Cakes","count":3}]}];
    const arr2 = [{"name":"Category 1","value":"Vegetables","children":[{"name":"Peas","value":"Peas","count":1}]},{"name":"Category 2","value":"Fruits","children":[{"name":"Apples","value":"Apples","count":3},{"name":"Bananas","value":"Bananas","count":2}]},{"name":"Category 3","value":"Desserts","children":[]}];
     
    let arr2Obj = Object.fromEntries(arr2.map(val => [val.name, val]))
    
    const res = arr1.map(({ name, value, children }) => {
      let arr2Children = ( arr2Obj[name] || {} ).children
      let childrenObj = Object.fromEntries(arr2Children.map(val => [val.name,val]))
      let newChildren = children.map( val => {
        let count = (childrenObj[val.name] || {}).count || 0
        return {...val,count}
      })
      return {name,value,children:newChildren}
    });
    console.log(res);
    .as-console-wrapper { max-height: 100% !important; top: auto; }

    P.S:-如果您的 array1 和 array2 始终处于排序状态,则您无需更改它的对象,您可以使用索引直接访问,对于孩子也是如此

    const arr1 = [{"name":"Category 1","value":"Vegetables","children":[{"name":"Carrots","value":"Carrots","count":2},{"name":"Peas","value":"Peas","count":1}]},{"name":"Category 2","value":"Fruits","children":[{"name":"Apples","value":"Apples","count":10},{"name":"Bananas","value":"Bananas","count":5}]},{"name":"Category 3","value":"Desserts","children":[{"name":"Ice Cream","value":"IceCream","count":3},{"name":"Cakes","value":"Cakes","count":3}]}];
    const arr2 = [{"name":"Category 1","value":"Vegetables","children":[{"name":"Peas","value":"Peas","count":1}]},{"name":"Category 2","value":"Fruits","children":[{"name":"Apples","value":"Apples","count":3},{"name":"Bananas","value":"Bananas","count":2}]},{"name":"Category 3","value":"Desserts","children":[]}];
    
    let createObject = (arr) => arr.reduce((op,[key,value])=>{
      op[key] = value
      return op
    },{})
    
    let arr2Obj = createObject(arr2.map(val => [val.name, val]))
    
    const res = arr1.map(({ name, value, children }) => {
      let arr2Children = ( arr2Obj[name] || {} ).children
      let childrenObj = createObject(arr2Children.map(val => [val.name,val]))
      let newChildren = children.map( val => {
        let count = (childrenObj[val.name] || {}).count || 0
        return {...val,count}
      })
      return {name,value,children:newChildren}
    });
    console.log(res);

    【讨论】:

    • 嗯。我收到一个错误,即 ObjectConstructor 类型上不存在“fromEntries”。
    • @Jake 你可以使用 polfill,让我用不使用 Object.fromEntries 的版本更新它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多