What is the best way to retrieve all the names stored within a nested object?

I am currently delving into the realm of JavaScript and my instructor has given me an exercise to create a function that will output an array containing all the names from the nested object below:

{
  name: 'grandma',
  daughter: {
    name: 'mother',
    daughter: {
      name: 'daughter',
      daughter: {
        name: 'granddaughter'
      }
    }
  }
}

My predicament is akin to a query posted on Stack Overflow, but the provided solution does not quite fit my scenario as my object structure lacks arrays. The code snippet I have managed to put together thus far looks like this:

    function convertToArray(obj) {
  const result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (typeof value === 'object') {
            result.push(convertToArray(value));
        }
        else {
            result.push(value);
        }
    }
    return result;
}

function extractNames(target) {

return convertToArray(target);

}

The output currently reads:

[ 'grandma', [ 'mother', [ 'daughter', [Array] ] ] ]

However, my instructor's expectations are aligned with:

['grandma', 'mother', 'daughter', 'granddaughter']

Access the codepen here

Answer №1

It is clear that the task involves pushing an array into another array, where all nested children are treated as separate elements in the array.

To address this issue, one approach is to iterate through the array and only add individual items to the final result set.

Alternatively, you can utilize certain built-in methods designed to work with arrays and flatten them into a single array without any nesting.

Here are some methods:

  • Array#concat, which creates a new array and is compatible with older versions of JavaScript.

    result = result.concat(toArray(value));
    
  • Array#push along with an array and Function#apply for accepting an array as parameter list. This method works directly on the original array and is compatible with older JS versions.

    Array.prototype.push.apply(result, toArray(value));
    [].push.apply(result, toArray(value));              // requires an additional empty array
    
  • Spread syntax ... for expanding an array into parameters. ES6

    result.push(...toArray(value));
    

    Spread syntax is a robust alternative to apply with broader applicability. Check out the examples for more clarity.

An example showcasing the use of spread syntax.

 function toArray(obj) {
    const result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (value && typeof value === 'object') { // exclude null
            result.push(...toArray(value));
            //          ^^^                          spread the array
        }
        else {
            result.push(value);
        }
    }
    return result;
}

function nameMatrioska(target) {
    return toArray(target);
}

var object = { name: 'grandma', daughter: { name: 'mother', daughter: { name: 'daughter', daughter: { name: 'granddaughter' } } } };

console.log(nameMatrioska(object));

Answer №2

It's important to use .concat instead of .push. Push adds a single item to an array, while concat combines two arrays together.

['grandmother'].concat(['mother', 'daughter'])
-> ['grandmother', 'mother', 'daughter']

Unlike the push method which alters the original array, the concat method creates a new array.

var a1 = [ 'grandmother' ];
a1.push( 'mother' );
console.log( a1 );
-> ['grandmother', 'mother']

var a2 = [ 'steve' ];
var result = a2.concat(['Jesus', 'Pedro']);
console.log( a1 );
-> ['steve']
console.log( result );
-> ['steve', 'Jesus', 'Pedro']

Answer №3

Give this a try

function convertToArray(obj) {
  var output = "";
    for (const property in obj) {
        const data = obj[property];
        if (typeof data === 'object') {
            output = output.concat(" " + convertToArray(data));
        }
        else {
            output = output.concat(data);
        }
    }

    return output; 
}

function extractWords(input) {

return convertToArray(input).split(" ");

}

Answer №4

function convertToArray(obj) {
  var resultArr = [];

  for (var property in obj) {
    var value = obj[property];
    if (typeof value === 'object') {
      resultArr = resultArr.concat(convertToArray(value))
    } else {
      resultArr.push(value);
    }
  }
  return resultArr;
}

function extractNames(targetObj) {
  return convertToArray(targetObj);
}

//CUSTOM
var familyNames = {
  name: 'grandma',
  daughter: {
    name: 'mother',
    daughter: {
      name: 'daughter',
      daughter: {
        name: 'granddaughter'
      }
    }
  }
};

console.log(extractNames(familyNames));
//Output: ["grandma", "mother", "daughter", "granddaughter"]

Answer №5

You are very close to finding the solution.
Remember to flatten your array in the final step.
A helpful tip: Always be cautious when checking for object types as JavaScript considers null and undefined as objects too!

function isObject(value) {
  if(value === undefined) return "Undefined";
  if(value === null) return "Null";
  const string = Object.prototype.toString.call(value);
  return string.slice(8, -1);
}

function collectPropertiesRec(object, propertyName) {
  const result = [ ];
  for(const currentPropertyName in object) {
    const value = object[currentPropertyName];
    if(isObject(value) === 'Object') {
        result.push(collectPropertiesRec(value, propertyName));
    }
    else if(currentPropertyName === propertyName) {
      result.push(value);
    }
  }
  return result;
}

function flattenDeep(arr1) {
    return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), [ ]);
  }

//USER
const names =  {
  name: 'grandma',
  daughter: {
    name: 'mother',
    daughter: {
      name: 'daughter',
      daughter: {
        name: 'granddaughter'
      }
    }
  }
};

var result = collectPropertiesRec(names, "name");
alert(flattenDeep(result).join(", "));

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

What steps should I take to ensure that clicking this button triggers the API request and returns the data in JSON format?

I'm attempting to have the button with id 'testp' return an api request in json format, however it seems to not be functioning properly. You can find the HTML code link here: https://github.com/atullu1234/REST-API-Developer-1/blob/main/js-bu ...

Retrieving the input from a textbox and appending it to a textarea

I am just starting out with jQuery and I have a query. Is it possible to achieve this task? I have a form that includes an input text box for a name. What I want to do is capture whatever the user types into that text box and add it to the first sentence i ...

Split a lengthy inventory into separate pages using EJS in combination with jQuery and AJAX

Currently, I am developing a dashboard using Node.js and express. At times, the lists I generate are excessively long, and I need to split them into pages with 20 items each. Users should be able to navigate between pages using buttons. However, I am unsur ...

Exploring the Differences Between setImmediate and nextTick

Today, a new version of Node.js (version 0.10) has been released, introducing the setImmediate feature. The API changes documentation recommends using it for recursive operations instead of nextTick. After checking what MDN says, it appears that setImmedi ...

Executing Windows cmd.exe commands from JavaScript code running on Node bash - A step-by-step guide

Is there a method to integrate a windows batch file within JavaScript code? Or is there a more secure approach to accomplish this using a node package? scripts.bat ECHO "JAVASCRIPT is AWESOME" PAUSE scripts.js // Code for executing the batch file // I ...

When the page loads, a JavaScript function is triggered

My switchDiv function in Javascript is being unexpectedly called when the page loads. It goes through each case in the switch statement, except for the default case. Does anyone know how to solve this issue? $(document).ready(function() { $("#be-button" ...

Next.js displays component twice

When examining the first image, it appears that Next.js rendered this element twice. Initially, I suspected the issue was related to the tables I used. However, even after removing the tables and replacing them with just , the element still renders twice, ...

What causes the return of 'undefined' during the execution of type coercion?

Can you explain why the type of a variable changes but the value remains undefined when trying to set it? let average; // Do I need to initialize with 'average = 0;' for it to work properly? for (const [oddName, odd] of Object.entries(game.odd ...

Having trouble transferring data from JavaScript to PHP via POST method

Hi there, this is my first time posting and I could really use some assistance. I have a bit of a roadblock with two Symfony forms on a page that don't seem to be working properly. The first form is for a contract, while the second one is used to pop ...

Tips for displaying a view with data fetched from various sources

I'm currently working on a project using backbone.js and I've encountered an issue with a model that doesn't need to synchronize with the server. This particular model is only meant to fetch user data for initializing other views; it acts as ...

Is there a way to make the Return key act like the Tab key in a jQuery

When the tab and enter keys are pressed, the following code exhibits different behaviors: --tab replaces the text field's value with the selected item's value and shifts focus to the next input box. --enter also changes the text field's va ...

Repurposing React key usage

section, I am curious to know if it is standard practice to reuse a React key from one component to another. For instance, in the Row component, the key obtained from the Column component is reused for mapping the children of Row. const Table = props =& ...

Adding external JSON data to a plain HTML document can be achieved through the process of

I have been experimenting with extracting data from an API in JSON format, but I am struggling to figure out how to convert the JSON tags into HTML elements. You can view a sample of the JSON data here. Does anyone know how to transform this JSON into DI ...

Is there a way to refine results based on geographic location?

Hello fellow coders! I need assistance finding a lightweight JavaScript code that can filter based on geographical location. This script needs to first determine if the GPS is enabled or not. If disabled, redirect to www.no.com. If enabled, it should chec ...

Using Ajax to call a PHP function within a WordPress website

I am looking to trigger a PHP function using AJAX. Below is the code snippet of my form: <form class="woocommerce-form woocommerce-form-login login" method="post"> <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-ro ...

unable to execute PHP code

I am attempting to execute a PHP file that will update a database. On Chrome, I am encountering this error: https://i.sstatic.net/3ruNL.png This is the code I have in my index.html file: <!DOCTYPE html> <html> <body> <input type ...

Guide on how to execute jasmine tests coded in TypeScript for Node.js applications

I am eager to test my express application developed in TypeScript. I am utilizing jasmine for writing test cases, webpack for bundling TypeScript files to JavaScript, and karma as the test runner. Please locate the following files: // about.service.ts - ...

Unlocking the attributes of Angular form elements: A guide

Imagine we have a form like this <form name="myForm" data-ng-controller="Ctrl"> <input name="input" data-ng-model="userType" data-description="User Type" required> </form> When working in the controller, we can refer to the input el ...

Disable form submission in MVC using a JavaScript function

In my project, there is an upload.ascx file that will be loaded inside a Jquery Popup. The upload.ascx file contains a File Upload control that uploads .xlsx and .xls files. To validate the file uploads and prevent unnecessary files from being uploaded, I ...

Is there a way to eliminate the mongoose event listener registered onConnect in the Socket.io Leak issue?

Whenever a user connects via socket.io, the following subscribe event is triggered: socket.on('subscribe', function(room) { console.log('joining room', room.id); socket.join(room.id); socket.roomName = room.id; // ...