Loop through a particular property within a nested object and add it to an array

Looking for a way to loop through each property of an object shown below in order to find the "nextStep" and add it to an array. The desired output is to have a single array variable containing all "nextStep" properties.

Input:

{
  "Product1": {
    "stepName": "step1",
    "stepOutputStatus": "normal",
    "nextStep": {
      "stepName": "step2",
      "stepOutputStatus": "normal",
      "nextStep": {
        "stepName": "step3",
        "stepOutputStatus": "warning",
        "nextStep": {
          "stepName": "step4",
          "stepOutputStatus": "warning",
          "nextStep": null
        }
      }
    }
  }
}

Expected Output:

[
  {
    "stepName": "step2",
    "stepOutputStatus": "normal"
  },
  {
    "stepName": "step3",
    "stepOutputStatus": "warning"
  },
  {
    "stepName": "step4",
    "stepOutputStatus": "warning"
  }
]

I attempted the following code, but it returns null due to scoping issue:

function iterateObject(obj) {
  var result = [];
  for (var key in obj) {
    if (
      obj[key] !== null &&
      typeof obj[key] === "object" &&
      key == "nextStep"
    ) {
      var data = this.iterateObject(obj[key]);
      result.push(data);
    }
  }
  return result;
}

iterateObject(obj);

Answer №1

One way to iterate through a JavaScript object is by using a generator function instead of recursion.
Simply move to the next step until it reaches the end.

If you're not familiar with the function * syntax, check out the MDN documentation for guidance.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

const product = {
  stepName: "step1",
  stepOutputStatus: "normal",
  nextStep: {
    stepName: "step2",
    stepOutputStatus: "normal",
    nextStep: {
      stepName: "step3",
      stepOutputStatus: "warning",
      nextStep: {
        stepName: "step4",
        stepOutputStatus: "warning",
        nextStep: null
      }
    }
  }
};

function* iterObj(obj) {
  while (obj.nextStep) {
    const { stepName, stepOutputStatus } = obj;
    yield { stepName, stepOutputStatus };
    obj = obj.nextStep;
  }
}

const iterator = iterObj(product);
console.log(Array.from(iterator));

Answer №2

You have the option to tackle this problem recursively using spread syntax and destructuring methods.

const data={"Product1":{"stepName":"step1","stepOutputStatus":"normal","nextStep":{"stepName":"step2","stepOutputStatus":"normal","nextStep":{"stepName":"step3","stepOutputStatus":"warning","nextStep":{"stepName":"step4","stepOutputStatus":"warning","nextStep":null}}}}}

function handleData({nextStep, ...rest}){
  const res = [];
  res.push(rest);
  if(nextStep){
     res.push(...handleData(nextStep));
  }
  return res;
}

const res = handleData(data.Product1);

console.log(res);

A more concise version:

const data={"Product1":{"stepName":"step1","stepOutputStatus":"normal","nextStep":{"stepName":"step2","stepOutputStatus":"normal","nextStep":{"stepName":"step3","stepOutputStatus":"warning","nextStep":{"stepName":"step4","stepOutputStatus":"warning","nextStep":null}}}}}

const handleData = ({nextStep, ...rest}) => [rest].concat(nextStep ? handleData(nextStep) : []);

const res = handleData(data.Product1);

console.log(res);

Answer №3

Recursive function designed to duplicate all keys except the specified one when going deeper into the object.

const obj = {
  "Product1": {
    "stepName": "step1",
    "stepOutputStatus": "normal",
    "nextStep": {
      "stepName": "step2",
      "stepOutputStatus": "normal",
      "nextStep": {
        "stepName": "step3",
        "stepOutputStatus": "warning",
        "nextStep": {
          "stepName": "step4",
          "stepOutputStatus": "warning",
          "nextStep": null
        }
      }
    }
  }
};

function extractDataForKey(key, pointer) {
  if (!pointer) {
    return [];
  }

  return Object.keys(pointer).reduce((result, x) => {
    if (x === key) {
      return [
        ...result,
        ...extractDataForKey(key, pointer[x]),
      ];
    }

    result[0][x] = pointer[x];

    return result;
  }, [{}]);
}

console.log(extractDataForKey('nextStep', obj.Product1));

Answer №4

let product={
  "Product1": {
    "stepName": "step1",
    "stepOutputStatus": "normal",
    "nextStep": {
      "stepName": "step2",
      "stepOutputStatus": "normal",
      "nextStep": {
        "stepName": "step3",
        "stepOutputStatus": "warning",
        "nextStep": {
          "stepName": "step4",
          "stepOutputStatus": "warning",
          "nextStep": null
        }
      }
    }
  }
}

let result=[];


function iterateObject(product) {
  while(product.nextStep!=null && product.hasOwnProperty('nextStep')){
    getNextStep(product.nextStep);
    product=product.nextStep;
  }
}

function getNextStep(object){
  if(object.hasOwnProperty('nextStep')){
     var data = {stepName:object.stepName,stepOutputStatus:object.stepOutputStatus};
     result.push(data);
  }
}

iterateObject(product["Product1"]);
console.log(result);

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

Ensure that the div's overflow extends halfway beyond the top of its parent element

I want to create a stylish bottom drawer slider that features a unique circular button fixed at the bottom of the page. When the drawer is closed, only half of the button should be visible (half a circle), and clicking on it will expand the drawer. Here&a ...

Execute a function on every item within a loop by utilizing jQuery

My view-model includes a data grid similar to the one displayed below <table> @foreach (var item in Model) //for(int i=0;i<Model.Count();i++) { using (Html.BeginForm("Edi ...

The code is running just fine when tested locally, but it seems to encounter an issue when accessed remotely, yielding

Currently, I am in the process of developing a dual twin setup using a Raspberry Pi. The goal is to simulate a continuous transmission of body temperature data, which is then sent to a server that stores the information in a MongoDB database. Everything fu ...

Achieving asynchronous results in the parent function with TypeScript: a guide

The code structure provided is as follows: import {socket} from './socket'; class A{ Execute(...args[]){ //logic with Promises SomeAsyncMethod1().then(fulfilled1); function fulfilled1(){ SomeAsyncMethod2(args).then(fulfilled2); ...

exploring enzyme's capabilities by testing multiple render methods in a single component

Struggling to test multiple render methods within a component using enzyme and jest with react. Any guidance on how to properly cover all the render methods? Here's a simplified representation of my large component structure through some pseudo code. ...

Iterating through every image displayed on a webpage

Two inquiries: What is the best way to efficiently loop through every image on a specific webpage and open each one in a new browser tab? Similar concept, but instead of opening in a new tab, I am interested in substituting different images for the ...

What is the best way to implement form validation and conditional markup using AngularJS?

What is the best way to display error messages using AngularJS and forms? I attempted to validate my form with the following code but it doesn't seem to work: <div class="form-group" ng-class="{'has-error': obj.title.$invalid}"> &l ...

Interacting between my React Native client and server.js

Currently, I am developing a project that utilizes react native, express, and MongoDB. My challenge lies in establishing communication between the react-native-js file and the node-js file. Specifically, when the submit button is clicked, I aim to pass a ...

Change elements in real-time

I have a requirement to adjust elements with the class .super-elem by adding an attribute adjusted="true". Initially, I can easily achieve this within the document's ready event : $(".super-elem").attr("adjusted", "true"); However, I may add more . ...

Are there equivalent npm variables like (`npm_config_`) available in yarn console scripts?

Utilizing variables in custom npm commands is possible (example taken from ): { "scripts": { "demo": "echo \"Hello $npm_config_first $npm_config_last\"" } } Can this functionality also be achieved ...

Transforming two child arrays within an object into a single array using Ramda

I am looking to transform an object into an array. The object I have is structured like this: const data = { t1: [ {"a": 1, "a1": 2}, {"b": 3, "b1": 4}, {"c": 5, "c1": 6} ], t2: [ {" ...

Retrieve a solitary row of information from a MySQL column

Here is an example of a MySQL database with the main table containing fields such as id, name, age, and photos: Table main: 3 John 22 photo1.jpg photo2.jpg photo3.jpg ph ...

Encountering PHP error when trying to access input type=file using jQuery/AJAX technique

I'm trying to use jQuery/AJAX to access the input type=file and pass the file value to a PHP page. However, I keep getting the following error message: Notice: Undefined index: file in D:\software installed\xampp\htdocs\contact-ma ...

Using JQuery, you can easily add a new row right after the row that you have

I need to insert a new row after the selected row, but my current code inserts the row at the end if no row is selected. Is there a way to fix this issue? strGridId = update_GridID(strGridId); var grid = jQuery('#' + strGridId); var columnModel ...

Tips for avoiding event listeners from being triggered multiple times

Implemented an event listener on an HTML element that was retrieved by className within the render method of highcharts, but for some reason, the listener is being triggered twice. The issue seems to be with the onClick handler in the highchart's rend ...

Ways to stop the default action in a confirm dialog while using Angular JS

Within my save function, I have the following: $scope.saveData = function () { if (confirm("Are you sure you want to save") === false) { return } // do saving When using the above code and clicking "yes," I encounter an error. Interestin ...

How to disable sorting on the top LI element using jQuery?

I currently have two separate UL elements that are being sorted using the jQuery Sortable plugin. Each UL contains between one and ten LI elements arranged in a list format. $(".sortable").sortable({ connectWith: ".sortable", cancel: '.no-dra ...

Set containing a nested collection of maps

Recently delving into the world of JavaScript and trying to grasp the concept of maps. This is the code snippet I'm currently working with: const topmap = new Map(); const map1 = new Map(); const map2 = new Map(); const set1 = new Set(); map1.set( ...

Retrieve the name of the php page after a redirection in an AJAX request

If the "profile.php" requested in the following code segment redirects to another page such as "login.php", how can we determine this? var xhr = new XMLHttpRequest(); xhr.open("GET", "profile.php", true); xhr.onreadystatechange = function() { if (xhr. ...

Struggling to figure out how to utilize UseEffect() effectively in updating State with a spread operator

I'm currently tackling a project in react utilizing graphql. The task at hand involves an object const [additionalInfo, setAdditionalInfo] = useEffect({}), containing selected objects that require appending with specific data fetched from the backen ...