Uncovering the deepest levels of nested arrays and objects in JavaScript without any fancy libraries - a step-by-step guide!

I have been struggling to find a solution to a seemingly simple problem. Despite searching through various sites and resources, I have not been able to figure out how to iterate over the innermost levels of a doubly nested data structure. I have tried using methods like forEach() and map() without any success.

Here is some background information on the data I am working with. The data provided below is extracted from an array that contains information about two retail stores. Each store object includes a property called visits, which stores an array of visit objects. Each visit object is uniquely identified by a visit date and includes a values property that holds an array of transactions, such as purchases or returns, made during that visit. In the complete dataset, the number of transactions can vary significantly from one date to another.

The specific tasks I need assistance with are as follows: (a) Change the property key to visitDate, (b) Rename the property values to transactions, (c) Remove 8 unnecessary properties (from storeID to storeVisitDate), while keeping the action and dollarAmount properties, and (d) Update the property dollarAmount to dollars.

I would greatly appreciate any help that can be provided. Thank you.

 [ ... ] 

Answer №1

That's spot on! Utilizing the .map() method can accomplish most of the tasks at hand. Thanks to the new ES6 standard, a lot of the processes have been simplified. The function provided below enables you to achieve your objectives without altering the original data:

array.map(store => {
  // Create a new object that retains all the store information, while updating the visits key in a new object
  return Object.assign({}, store, {
    // Iterate over the visits array, updating the key to visitDate
    visits: store.visits.map(({ key: visitDate, values }) => {
      return {
        // Create an object with visit date
        visitDate,
        // Perform destructuring to create objects of action and dollars
        transactions: values.map(({ action, dollarAmount: dollars }) => ({ action, dollars }))
      };
    })
  });
});

Answer №2

(Check out the working example on jsFiddle here - just open the JS console to view the converted data set)

Here are a few key points regarding the solution provided below:

  • It has the capability to handle data sets with more keys than the sample provided. This ensures flexibility for complex data structures.
  • It predominantly utilizes the "map" function instead of manual array iteration for improved code readability.

    // Iterates over all stores
    stores.map(function(store) {
      // Within each store, iterates over all visits
      store.visits.map(function(visit) {
        // Renames 'key' to 'visitDate' and 'values' to 'transactions'
        // Then removes the old names ('key' and 'values')
        visit.visitDate = visit.key;
        visit.transactions = visit.values;
        delete visit.key;
        delete visit.values;
    
        // Replaces each transaction with a simplified map containing only 'action' and 'dollars'
        visit.transactions = visit.transactions.map(function(tx) {
          return {
            action: tx.action,
            dollars: tx.dollarAmount
          };
        });
      });
    });
    

It's worth noting that map() is supported in IE9 and newer.

Answer №3

To update property names, you can simply create a new property with the desired name and the same value, then use the delete operator to remove the old property.

In this case, it would be more organized to consolidate properties b, c, and d by leveraging the map() function to create a new array of optimized transactions and assign it to the updated transactions property.

// Function to update data properties
function modifyData(entries) {
  // Loop through each entry and update property names
  for (var iEntry = 0; iEntry < entries.length; iEntry++) {
    var entry = entries[iEntry];

    for (var iVisit = 0; iVisit < entry.visits.length; iVisit++) {
      var visit = entry.visits[iVisit];

      // Update property key to visitDate
      // Create a new property with the same value and then delete the old property
      visit.visitDate = visit.key;
      delete visit.key;

      // Update property values to transactions
      // Create a new property with the same value and then delete the old property
      // Delete redundant properties and rename specific properties
      visit.transactions = visit.values.map(function(transaction) {
        return {
          action: transaction.action,
          dollars: transaction.dollarAmount
        }
      });
      delete visit.values;
    }
  }

  console.log(entries);
}

var entries = [
 // Sample data entries here
];

modifyData(entries);

Answer №4

Let's assume your array is named array, here is a suggestion:

array.forEach(function(item, index, array) {
   item.data = item.data.map(function(dataItem, index, array) {
      dataItem.visitDate = dataItem.timestamp;
      delete dataItem.timestamp;
      dataItem.transactions = dataItem.values.map(function(value, index, array) {
         return {action: value.task, amount: value.money};
      });
      delete dataItem.values;
      return dataItem;
   });
});

Answer №5

Given that this is 'data' rather than in-memory objects, it seems likely that you extracted it from JSON using the JSON.parse method. (If not, you can still achieve the same by initially using JSON.stringify)

Were you aware that JSON.parse allows you to pass in a function to customize the parsing process? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

Therefore...

updatedData = JSON.parse(dataString, function(key, value) {
 if(key === "key") {this.visitDate = value; return;}
 if(key === "values"){this.transactions = value; return;}
 if(key === "somethingYouDontWant"){return;}
 //etc...
 return value;
})

Answer №6

Here is a customized approach using the Array.map() method along with the delete operator:

let propertiesToDelete = ["prop1", "prop2", "prop3"];

// arrayData represents the original array
arrayData.map(function(data){
    data['subData'].map(function(subData){
        subData['newProperty'] = subData['oldProperty'];
        delete subData['oldProperty'];
        
        subData['nestedData'].map(function(nestedData){
            nestedData['newValue'] = nestedData['originalValue'];
            delete nestedData['originalValue'];

            propertiesToDelete.forEach(function(prop){
                delete nestedData[prop];
            });
        });

        subData['modifiedData'] = subData['nestedData'];
        delete subData['nestedData'];
    });
});

Answer №7

Presented here is an alternative approach, featuring code that is easily understandable but lacks optimization.

let obj = {}, key;
data.forEach((item) => {
  item.visits.forEach((visit) => {
    visit.visitDate = visit.key; 
    delete visit.key;
    visit.transactions = [];
    visit.values.forEach((value) => {
      obj = {};
      for (key in value) {
        if (value.hasOwnProperty(key) && retain.indexOf(key) > -1) {
          obj[key] = value[key];
        }
      }
      visit.transactions.push(obj);
    });
    delete visit.values;
  });
console.log(item);
});

Answer №8

This code is written in pure JavaScript without the use of any external library. It utilizes a simple mapping technique:

 var result = input.map(function(data){
      data.subItems = data.subItems.map(function (item){
        return {
          date: item.date,
          details: item.values.map(function(value){
            return {
              action: value.action,
              amount: value.amount
            };
          })
        };
      });
      return data;
    });

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 ngModel directive automatically clears the checkbox's Checked status

Currently, my Angular code is set up to validate a checkbox using ng-model: <input type="checkbox" name="news1" value="news1" ng-model="news" <c:if test="${xxxx == yes'}">checked="checked"></c:if>> <label ng-click="news1();"&g ...

Enhance the attributes of a collection of objects using values from a different array

Looking for a way to enhance a set of objects with properties sourced from another array? I have two arrays at hand. The first one contains a series of objects, while the second one consists of integers. My goal is to attribute a new property to each objec ...

JavaScript and AJAX are showing an error message that says: "ReferenceError: x is not

I am currently working on a jQuery function that retrieves the value from a PHP-generated checkbox and sends it through AJAX. The value being sent is always a single word consisting only of letters. Here is the script I have written: <script type="text ...

Homepage divided in two sections akin to the Tumblr landing page

Have you ever visited www.tumblr.com and noticed the '30 reasons...' link on the registration page that slides up and reveals a second page? I've been trying to figure out how they achieve this cool effect. Most tutorials show how to scroll ...

Tips for preventing FormLabel components from turning blue when a radio button is selected

Currently, I am working on a Reactjs project that utilizes Material Ui components. In this project, I am tasked with creating a form to generate a new event where users can select the event location type from three options - In-Person, Hybrid, and Virtual ...

The ngCordova FileTransfer is not providing the HTTP status code when retrieving a file from an FTP server

I am attempting to retrieve a file from an FTP server using Cordova. To accomplish this, I have installed the ngCordova and Filetransfer plugins. Below is the snippet of code I am working with: angular.module('TestApp', ['ionic', &apos ...

Tips for saving a value within a jQuery function for future use in a different function

I have a situation where I receive a value from a jQuery function that I need to pass to another function. How can I achieve this? jQuery.getJSON(url+"&startDate="+startDate+"&endDate="+endDate+"&jobId="+jobId+"&type="+type, function(data) ...

Setting up a personalized JSPM registry configuration

I have chosen to use Verdaccio as the platform for hosting a private package. In my current project, I am looking to incorporate this package locally. The package has been successfully published and is now hosted on Verdaccio running on localhost (http://l ...

What is the best method for retaining the complete YQL outcome within a JavaScript object?

I am trying to store the output of my YQL Query in a JavaScript object Here is my query: SELECT * FROM html WHERE url="http://myurl.com" and xpath="/html/body/center/table[1]/tr" Can someone guide me on how to proceed? I have gone through the YQL docu ...

What are the best strategies for creating HTML website designs that are both scalable, adaptable, and versatile?

As a beginner in HTML website design, I have recently started using HTML, CSS, jQuery, and JavaScript for designing websites. After creating a site with almost forty webpages, the client requirements are changing, requiring changes to be made across all ...

Java code to extract and delete a section of a website on a webpage

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ View view = inflater.inflate(R.layout.fwebview, container, false); webView = (WebView) view.findViewById(R.id.webView); String url = ge ...

Sorting through an array of objects nested within another array of objects

I'm currently working on a MERN app where I retrieve all albums using axios. This is the structure of the data: [ { title: "", artist: "", reviews: [ { username: "", comment: "", }, { ...

Discover the unique value in Angular if it is not present in the list

I have a question about handling values in a list and displaying the "create value" component to the user when needed. How can I efficiently compare search input values with those in the list and determine if a match exists? If no match is found, the "cr ...

Elevating the Components of an Array Similar to a Numeric Value

Currently, I am in the process of developing a Sudoku-solving program. In order to determine the solution for the puzzle, my program interprets 0s as vacant slots and generates an array that matches the total number of zeros present in the Sudoku puzzle. S ...

An operator in rxjs that transforms an Observable of lists containing type X into an Observable of type X

Currently, I am facing a challenge while dealing with an API that is not very user-friendly using Angular HTTP and rxjs. My goal is to retrieve an Observable<List<Object>> from my service. Here's a snippet of the JSON output obtained from ...

Trigger .gif on hover using ng-repeat in AngularJS

Many solutions to this problem involve using jQuery, such as the following examples: Stop a gif animation onload, on mouseover start the activation and Animating a gif on hover. However, I'm interested in achieving the same functionality using Angular ...

Having difficulties accessing the properties of a dynamically created JSON object with ng-repeat functionality

Within an ng-repeat loop, I have implemented a radio button that assigns the entire person object to a scope variable as shown below: <li ng-repeat="person in people"> <label>{{person.name}} <input type="radio" ng-model="$parent.s ...

Are you prepared for changing DropDowns?

To ensure users make a selection from a specific dropdown menu, I have implemented the following code to trigger an alert if they fail to do so: <script> function checkSelection(){ var sel = document.getElementById(' ...

Navigating through a collection of objects

My array consists of objects, each having the following structure: var car = { make: "", model: "", price: "" } I am attempting to iterate through each object and check if a specific property is defined in this manner: for (i = 0; i <= ...

Retrieve the original content of a file uploaded by a user in Node.js using Express

Can we extract the raw file contents from a user uploaded file using Node.js Express? app.post('/images', upload.single('image'), async (req, res) => { const file = req.file ... I have come to realize that the file variable in t ...