Сопоставление массивов с использованием объединения или пересечения для создания третьего массива - PullRequest
0 голосов
/ 16 июня 2019

Я пытаюсь решить проблему в Angular 7, где мне нужно написать функцию, которая принимает два массива объектов, в данном случае первый и второй, и возвращает третий массив.

Третий массив очень похож на первый массив, но значение ключа count в массиве children зависит от того, есть ли какие-либо children во втором массиве или, если они присутствуют, отражают значение count в этом объекте. Есть ли функция карты массива в угловых, которая может решить эту проблему?

Первый массив:

[
    {
        "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}
        ]
    }
]

Ответы [ 2 ]

2 голосов
/ 16 июня 2019

Вы можете сделать это довольно просто с помощью map и find, затем 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; }
1 голос
/ 16 июня 2019

Здесь идея:

  • Сначала измените второй массив на объект, чтобы стало легче находить значения в нем
  • Теперь переберите массив 1 и возьмите соответствующих потомков из массива 2
  • Цикл для потомков массива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; }

PS: - Если ваши массивы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 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);
...