Combine arrays using union or intersection to generate a new array

Seeking a solution in Angular 7 for a problem involving the creation of a function that operates on two arrays of objects. The goal is to generate a third array based on the first and second arrays.

The structure of the third array closely resembles the first array, with the key count within the children array being influenced by the presence or absence of corresponding children in the second array. Is there an angular array mapping function capable of handling this task?

First Array:

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

Second Array

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

Third Array

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

Answer №1

If you want to achieve this task easily, you can use a combination of map and find, followed by reducing the array.

const firstArray = [{"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 secondArray = [{"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 result = firstArray.map(({ name, value, children }) => {
  let foundItem = secondArray.find(({ name: n, value: v }) => n == name && v == value);
  if (foundItem) children = children.concat(foundItem.children).reduce((acc, cur) => {
    let index = acc.findIndex(({ name: n }) => n == cur.name);
    if (index > -1) acc[index].count += cur.count;
    else acc.push(cur);
    return acc;
  }, []);
  return { name, value, children };
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Answer №2

Here's the idea:

  • Begin by converting the second array into an object to simplify finding values within it.
  • Next, iterate through array1 and extract the corresponding children from array2.
  • Loop through the children of array1 and update the values based on the children from 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 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:- If your array1 and array2 are always in sorted manner than you need not to change it object and you can directly access using index, same for the children

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);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The method hasOwnProperty does not function as intended

Upon receiving a JSON object from the server ({error:true}), I attempted to verify if the key "error" exists. Surprisingly, the function hasOwnProperty returned false. Here is the snippet of code that led to this unexpected result: $http({ header ...

Particles.js fails to persist as I scroll down the HTML page

After creating a website page, I incorporated Particles.js for the background. However, when I scroll down, the particles seem to be confined to the initial corner of the screen and do not continue downward. Here are my current particle settings: #particl ...

The function item$.take cannot be found, resulting in a TypeError: "item$.take is not a function"

I am currently facing an issue with the take(1) function not working as expected with my Angular Firebase object. I have tried using valuechanges and snapshotchanges as alternatives, but they do not solve the problem for me due to other issues I encounter. ...

Finding results in AngularJS by typing at least 4 characters into the input field

I am using a MySQL database to search with AngularJS. How can I set it up so that the search only triggers when at least 4 characters are inputted? Here is the HTML code: <div class="search"> <form action="" method="post" class="searchform" &g ...

What is the process for creating an Account SAS token for Azure Storage?

My goal is to have access to all containers and blobs in storage. The Account SAS token will be generated server-side within my Node.js code, and the client will obtain it by calling the API I created. While Azure Shell allows manual creation of a SAS toke ...

Using AngularJS with the Chosen Plugin to pre-select a value in a dropdown menu

After following the guidance from this URL, I successfully incorporated the chosen plugin into Angular.js. Now that I can retrieve the value, my next objective is to have the selected value be pre-selected in the chosen dropdown menu. If anyone has a sim ...

Variations in output observed from angular function across various sections within DOM

After fetching a list of permissions in the background, my goal is to display a page or an error message based on whether the user has the required permissions. I encountered an unusual issue where both sections of the page are being displayed despite hav ...

Angular Tip: Display data in a dropdown using a select element

When I have two select elements and want to display values if they exist: page.ts import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app ...

How to use jQuery to dynamically assign a class to an li element

I'm attempting to use jQuery to add the 'block' class to specific li elements, but for some reason the class isn't being applied. The goal of the program is to display time slots and disable certain ones if they are blocked. Here's ...

What exactly is the purpose of the script type importmap?

Can you explain the role of <script type="importmap"> and why it has become necessary for my code to function properly? <script type="importmap"> { "imports": { "three": "http ...

Utilizing ng-disabled with a custom directive

Is it possible to achieve the following: <directiveName parameter1=value1 parameter2=value2 ng-disabled="true"> </directiveName> I tried this but couldn't get it to work and didn't find many examples of its use. However, I can togg ...

What could be causing the rapid breakage of the socket in Ionic 3's Bluetooth Serial after just a short period

Although the code appears to be functioning correctly, it loses connection shortly after establishing it. This snippet contains the relevant code: import { Component } from '@angular/core'; import { Platform, NavController, ToastController, Ref ...

What is the best method for linking my chatbot's user interface to the API.AI server host using either the Python SDK or JavaScript

Looking for a way to seamlessly integrate my chatbot UI, created using HTML and CSS, with the API.AI server using the token provided by API.AI and Python SDK? Below is the HTML code snippet for reference: <!DOCTYPE html> <html> <head> ...

Guide on implementing Google sign in functionality in Angular 6 and redirecting on successful sign in

Seeking Clarity I recently implemented a component that presents a Google Sign In button to unauthenticated users. Upon signing in, the access token is sent to my server for verification, which then returns a jsonwebtoken. I followed Google's documen ...

Angular 4: Implementing toggle switch functionality in Angular 4 by binding boolean values retrieved from the database

Within my application, I am facing an issue with binding a toggle switch to data stored in the database. The data in the database is represented by a field called Status, which can have values of True or False. My goal is to incorporate toggle switch butto ...

What is the best way to assign a unique ID to every <td> element within a table using React Js?

Hello everyone. I am currently working on assigning unique ids to each td in a table based on data received through an API. This is what my code looks like so far. CodeSandbox const assignIdsToTableData = (data) => { var items = Object.values(data)[0 ...

javascript The final position achieved through requestAnimationFrame is never precise

let pf = document.querySelectorAll('.pf'); for (let i of pf) { Object.assign(i.style, { left: '400px' }) } function shiftLetters() { let start = performance.now(); let dist = -400; let dur = 500; const logoAnimate = ( ...

Nodejs functions properly on a local machine, however, it encounters issues when deployed on a VPS

My nodejs/javascript code seems to be running fine on my local pc, but when I try to run it on my vps, it's not working properly. Even though I have the same node_modules installed and the code is identical. Here's a snippet of my code for refere ...

Issue with Npm installation command on Windows 7 64-bit system

When I run the command "npm install" from my project folder, I encounter the following errors: Error: Windows_NT 6.1.7601 Node version: v6.10.3 NPM version: v3.10.10 Code: ENOTFOUND Network error: getaddrinfo ENOTFOUND registry.npmjs.org regist ...

Exploring Angular 4.3's HTTP Interceptor Retry功能

As I delve into my first attempt at coding, I find myself faced with the challenge of capturing 401 errors using HttpInterceptor. My goal is to generate a new auth token based on a certain condition and then retry the process with that token in place. Howe ...