0

I have complex json like this:

const lstCountry = {
   "cols": ["id", "countryName", "area"],
   "data": [
       ["1", "Russia", "17098242"],
       ["2", "Canada", "9970610"],
       ["3", "China", "9640821"],
       ["4", "United States", "9629091"],
       ["5", "Brazil", "8514877"],
       ["6", "Australia", "7741220"],
       ["7", "India", "3287263"],
       ["8", "Argentina", "2780400"],
       ["9", "Kazakhstan", "2724900"],
       ["10", "Sudan", "2505813"]
    ]
};

Now i want to convert into simple array as a output like this :

const countryList = [
    { "id": "1", "countryName": "Russia", "area": "17098242" },
    { "id": "2", "countryName": "Canada", "area": "9970610" },
    { "id": "3", "countryName": "China", "area": "9640821" },
    { "id": "4", "countryName": "United States", "area": "9629091" },
    { "id": "5", "countryName": "Brazil", "area": "8514877" },
    { "id": "6", "countryName": "Australia", "area": "7741220" },
    { "id": "7", "countryName": "India", "area": "3287263" },
    { "id": "8", "countryName": "Argentina", "area": "2780400" },
    { "id": "9", "countryName": "Kazakhstan", "area": "2724900" },
    { "id": "10", "countryName": "Sudan", "area": "2505813" },
];

I have already tried below but got output using index as a key, So how can i convert that key with cols array as a key and another data array as a value and generate my own array with these key and value combination.

Or Is there any easy way to archive this like using map, reduce?

Already tried this :

let mainData = [];
for (let i = 1; i < Object.keys(data).length; i++) {
    const eleData = data[Object.keys(data)[i]];
    for (let j = 0; j < eleData.length; j++) {
        const element = Object.assign({}, eleData[j]);
        mainData.push(element);
    };            
};
console.log('mainData:', mainData)

Tried function output:

const mainData = [
    { "0": "1", "1": "Russia", "2": "17098242" },
    { "0": "2", "1": "Canada", "2": "9970610" },
    { "0": "3", "1": "China", "2": "9640821" },
    { "0": "4", "1": "United States", "2": "9629091" },
    { "0": "5", "1": "Brazil", "2": "8514877" },
    { "0": "6", "1": "Australia", "2": "7741220" },
    { "0": "7", "1": "India", "2": "3287263" },
    { "0": "8", "1": "Argentina", "2": "2780400" },
    { "0": "9", "1": "Kazakhstan", "2": "2724900" },
    { "0": "10", "1": "Sudan", "2": "2505813" },
];
3
  • And what happened with what you already tried? Did you try doing it with map and/or reduce? Commented Aug 14, 2019 at 7:32
  • I had updated question, but i got answer from below answer, let just wait for more few minutes to accept as a answer Commented Aug 14, 2019 at 7:39
  • Can you try this? var data= lstCountry.data.map(item=> { return { id:item[0], countryName: item[1], area:item[2]}}); console.log(data); Commented Aug 14, 2019 at 7:40

6 Answers 6

4

You can simply map over each object and create each object pertaining to each column using reduce:

const lstCountry = {
   "cols": ["id", "countryName", "area"],
   "data": [
       ["1", "Russia", "17098242"],
       ["2", "Canada", "9970610"],
       ["3", "China", "9640821"],
       ["4", "United States", "9629091"],
       ["5", "Brazil", "8514877"],
       ["6", "Australia", "7741220"],
       ["7", "India", "3287263"],
       ["8", "Argentina", "2780400"],
       ["9", "Kazakhstan", "2724900"],
       ["10", "Sudan", "2505813"]
    ]
};

const { cols, data } = lstCountry

console.log(data.map(arr => arr.reduce((a, e, i) => (a[cols[i]] = e, a), {})))

EDIT: As a function:

const fn = (cols, data) => data.map(arr => arr.reduce((a, e, i) => (a[cols[i]] = e, a), {}))

console.log(fn(['test'], [[1],[2],[3],[4]]))
console.log(fn(['test', 'true'], [[1,1],[2,1],[3,1],[4,1]]))

The solution is the most performance-oriented as there are only two loops, rather than three, according to this JSPerf:

JSPerf

Sign up to request clarification or add additional context in comments.

3 Comments

I don't want to take cols and data as a static, is there any way to make it dynamic if i change name from cols and data to columns and lstData than i can also use same function?
@ShashikantDevani Look at my second code snippet :)
@ShashikantDevani No problem. If you ever need more help, feel free to ask.
2

You could map entries of the object and build new objects.

var lstCountry = { cols: ["id", "countryName", "area"], data: [["1", "Russia", "17098242"], ["2", "Canada", "9970610"], ["3", "China", "9640821"], ["4", "United States", "9629091"], ["5", "Brazil", "8514877"], ["6", "Australia", "7741220"], ["7", "India", "3287263"], ["8", "Argentina", "2780400"], ["9", "Kazakhstan", "2724900"], ["10", "Sudan", "2505813"]] },
    result = lstCountry.data.map(a =>
        Object.fromEntries(a.map((v, i) => [lstCountry.cols[i], v])));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

An EDGE version with Object.assign.

const getObjects = (keys, data) => data.map(a =>
        Object.assign(...a.map((v, i) => ({ [keys[i]]: v }))));

var lstCountry = { cols: ["id", "countryName", "area"], data: [["1", "Russia", "17098242"], ["2", "Canada", "9970610"], ["3", "China", "9640821"], ["4", "United States", "9629091"], ["5", "Brazil", "8514877"], ["6", "Australia", "7741220"], ["7", "India", "3287263"], ["8", "Argentina", "2780400"], ["9", "Kazakhstan", "2724900"], ["10", "Sudan", "2505813"]] },
    result = getObjects(lstCountry.cols, lstCountry.data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

3 Comments

That's cool. Didn't know fromEntries existed +1. Though, it's not supported in edge.
I don't want to take cols and data as a static, is there any way to make it dynamic if i change name from cols and data to columns and lstData than i can also use same function?
you could take a function and hand over the data array and the keys array, like in the second example.
2

Map the .data property, and use Object.fromEntries to transform each .data subarray to an object based on the keys in the cols:

const lstCountry = {
   "cols": ["id", "countryName", "area"],
   "data": [
       ["1", "Russia", "17098242"],
       ["2", "Canada", "9970610"],
       ["3", "China", "9640821"],
       ["4", "United States", "9629091"],
       ["5", "Brazil", "8514877"],
       ["6", "Australia", "7741220"],
       ["7", "India", "3287263"],
       ["8", "Argentina", "2780400"],
       ["9", "Kazakhstan", "2724900"],
       ["10", "Sudan", "2505813"]
    ]
};

const countryList = lstCountry.data.map(
  vals => Object.fromEntries(
    vals.map((val, i) => [lstCountry.cols[i], val])
  )
);
console.log(countryList);

For dynamic property names in the lstCountry object, just use bracket notation instead:

const lstCountry = {
   "cols": ["id", "countryName", "area"],
   "data": [
       ["1", "Russia", "17098242"],
       ["2", "Canada", "9970610"],
       ["3", "China", "9640821"],
       ["4", "United States", "9629091"],
       ["5", "Brazil", "8514877"],
       ["6", "Australia", "7741220"],
       ["7", "India", "3287263"],
       ["8", "Argentina", "2780400"],
       ["9", "Kazakhstan", "2724900"],
       ["10", "Sudan", "2505813"]
    ]
};

const keyProp = 'cols';
const valProp = 'data';

const countryList = lstCountry[valProp].map(
  vals => Object.fromEntries(
    vals.map((val, i) => [lstCountry[keyProp][i], val])
  )
);
console.log(countryList);

4 Comments

I don't want to take cols and data as a static, is there any way to make it dynamic if i change name from cols and data to columns and lstData than i can also use same function?
Just use bracket notation instead
Yeah it make sense but i know if it's come from backend site (both are dynamic) object?
Just put them into the keyProp and valProp variables like in the snippet in the answer
2

One option is using map to loop thru the data array. Use reduce to construct the object.

const lstCountry = {
  "cols": ["id", "countryName", "area"],
  "data": [
    ["1", "Russia", "17098242"],
    ["2", "Canada", "9970610"],
    ["3", "China", "9640821"],
    ["4", "United States", "9629091"],
    ["5", "Brazil", "8514877"],
    ["6", "Australia", "7741220"],
    ["7", "India", "3287263"],
    ["8", "Argentina", "2780400"],
    ["9", "Kazakhstan", "2724900"],
    ["10", "Sudan", "2505813"]
  ]
};

const rows = lstCountry['data'];
const cols = lstCountry['cols'];

const countryList = rows.map(o => o.reduce((c, v, i) => Object.assign(c, {[cols[i]]: v}), {}));

console.log(countryList);

3 Comments

I don't want to take cols and data as a static, is there any way to make it dynamic if i change name from cols and data to columns and lstData than i can also use same function?
You can assign it in a variable or something :)
Yeah it make sense but i know if it's come from backend site (both are dynamic) object?
0

Use map with Object.fromEntries really simply like so:

const lstCountry = {"cols":["id","countryName","area"],"data":[["1","Russia","17098242"],["2","Canada","9970610"],["3","China","9640821"],["4","United States","9629091"],["5","Brazil","8514877"],["6","Australia","7741220"],["7","India","3287263"],["8","Argentina","2780400"],["9","Kazakhstan","2724900"],["10","Sudan","2505813"]]};

const countryList = lstCountry.data.map(e => Object.fromEntries(lstCountry.cols.map((f, i) => [f, e[i]])));

console.log(countryList);
.as-console-wrapper { max-height: 100% !important; top: auto; }

1 Comment

I don't want to take cols and data as a static, is there any way to make it dynamic if i change name from cols and data to columns and lstData than i can also use same function?
-1

You can do this with Array#map and Array#reduce.

This solution assumes that the length of your cols is the same for each row in data.

const countries = {
   "cols": ["id", "countryName", "area"],
   "data": [
       ["1", "Russia", "17098242"],
       ["2", "Canada", "9970610"],
       ["3", "China", "9640821"],
       ["4", "United States", "9629091"],
       ["5", "Brazil", "8514877"],
       ["6", "Australia", "7741220"],
       ["7", "India", "3287263"],
       ["8", "Argentina", "2780400"],
       ["9", "Kazakhstan", "2724900"],
       ["10", "Sudan", "2505813"]
    ]
};

const res = countries.data.map(arr=>{
  return countries.cols.reduce((a,c,i)=>{
    return {[c]:arr[i], ...a}
  },{})
});

console.log(res);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.