简体   繁体   中英

Convert a multi-dimensional array of objects to single-dimensional array of objects Javascript

I have a multi-dimensional array of objects that is wreaking havoc on Angular's ng-repeat, so I want to convert it to a single-dimensional array. I tried and failed to do so using forEach . When I try to use console.log(newData) after running the function, it returns an empty array. Am I making it too simple, or did I make a stupid mistake?

 //Sample data (allData): var allData = [{ "period": 4, "uploadDate": "2015-11-19T21:00:00.000Z", "section": [{ "transferCode": 8675309, "details": [{ "voucherNumber": [34, 22], "vendor": "jimmy", "description": "blah ", "amount": "t 45,555.00" }] }] }, { "period": 4, "uploadDate": "2015-11-19T21:00:00.000Z", "section": [{ "transferCode": 45576543, "details": [{ "voucherNumber": [22, 33], "vendor": "Jonson", "description": "trap music ", "amount": "t 12,345.00" }] }] }] //code to push to new array: var newData = []; function newArray() { allData.forEach(function(top) { top.section.forEach(function(mid) { mid.details.forEach(function(low) { newData.push({ vendor: low.vendor, voucherNumber: low.voucherNumber, description: low.description, amount: low.amount, transferCode: mid.transferCode, uploadDate: top.uploadDate, period: top.period }) }) }) }) return newData; } newArray(); document.body.textContent = JSON.stringify(newData); 

This might help eleviate you from being too literal... Note that the container arrays are skipped (eg "section" and "details")

// Helper functions
function isArray(obj) {return Array.isArray ? Array.isArray(obj) : Object.prototype.toString.call(obj) === '[object Array]';}
function isNumber(val) { return Object.prototype.toString.call(val) === '[object Number]' && isFinite(val);}


// Flatten object
function flatten(arg, out) {
    out = out || {};
    for (var prop in arg) {
        var val = arg[prop];

        if (isArray(val)) {
            for (var i = 0; i < val.length; i++) {

                // introspect if the array is just an array of numbers
                var valin = val[i];
                if (isArray(val) && isNumber(valin)) {

                    // just set to the number array and move along.
                    out[prop] = val;
                    break;
                } else {
                    flatten(valin, out);
                }
            }

        // continue looking deeper
        } else if (typeof val == "object") {
            flatten(val, out); 

        // get the value
        } else {
            out[prop] = val; 
        }
    }
    return out;
}


// Put each flattened object into a new data array
var data = [];
for (var i = 0; i < allData.length; i++) {
    data.push(flatten(allData[i]));
}

console.log(JSON.stringify(data));

I am not sure, that your presented solution is what you want, so here an interpretation of your data and how to build an redundant data set.

This is the part, where I changed the code for:

"details": [{
    "voucherNumber": [34, 22, 23],
    "vendor": ["jimmy", "sam", "jones"],
    "description": ["blah", "blach", "bluch"],
    "amount": [45555, 232, 345346]
}]

Every property in details contains an array with the same length (hopefully). I assume, that every index belongs together, like 34, jimmy, blah, 45555 .

The code part for it looks for the keys in details and then for the length of every array of the properties. Then it loops over the length and the keys and assign the key/value pairs. After all values for one index are collected, the object is pushed to the result array.

 var allData = [{ "period": 4, "uploadDate": "2015-11-19T21:00:00.000Z", "section": [{ "transferCode": 8675309, "details": [{ "voucherNumber": [34, 22, 23], "vendor": ["jimmy", "sam", "jones"], "description": ["blah", "blach", "bluch"], "amount": [45555, 232, 345346] }] }] }, { "period": 4, "uploadDate": "2015-11-19T21:00:00.000Z", "section": [{ "transferCode": 45576543, "details": [{ "voucherNumber": [22, 33], "vendor": ["Jonson", "ronson"], "description": ["trap music", "jesus"], "amount": [12345, 23234] }] }] }]; function newArray(data) { var newData = []; data.forEach(function (top) { top.section.forEach(function (mid) { mid.details.forEach(function (low) { var keys = Object.keys(low), length = keys.reduce(function (r, a) { return Math.max(r, low[a].length); }, 0), obj, i = 0; while (i < length) { obj = { uploadDate: top.uploadDate, period: top.period }; keys.forEach(function (k) { obj[k] = low[k][i]; }); newData.push(obj); i++; } }); }); }); return newData; } document.write('<pre>' + JSON.stringify(newArray(allData), 0, 4) + '</pre>'); 

Ok, got it working with some helpful advice and taking it in a bit of a different direction:

var allData = [{
  "period": 4,
  "uploadDate": "2015-11-19T21:00:00.000Z",
  "section": [{
    "transferCode": 8675309,
    "details": [{
      "voucherNumber": [34, 22, 23],
      "vendor": ["jimmy", "sam", "jones"],
      "description": ["blah", "blach", "bluch"],
      "amount": [45555, 232, 345346]
    }]
  }]
},
{
  "period": 4,
  "uploadDate": "2015-11-19T21:00:00.000Z",
  "section": [{
    "transferCode": 45576543,
    "details": [{
      "voucherNumber": [22, 33],
      "vendor": ["Jonson", "ronson"],
      "description": ["trap music", "jesus"],
      "amount": [12345, 23234]
    }]
  }]
}];

var newData = [];

function newArray() {
  allData.forEach(function(top) {
    top.section.forEach(function(mid) {
      mid.details.forEach(function(low) {
        low.vendor.forEach(function(vend){
            low.voucherNumber.forEach(function(vouch) {
                low.description.forEach(function(desc) {
                    low.amount.forEach(function(amt) {
                        newData.push({
                            vendor: vend.vendor,
                            voucherNumber: vouch.voucherNumber,
                            description: desc.description,
                            amount: amt.amount,
                            transferCode: mid.transferCode,
                            uploadDate: top.uploadDate,
                            period: top.period
                        });
                    });
                });
            });
        });
      });
    });
  });
  return newData;
}
newArray();
document.body.textContent = JSON.stringify(newData);
// var test = JSON.stringify(newData);
// console.log(test);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM