3

I have following array of objects :

[
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "quis ut",
    "completed": false
  }
]

I want following as output :

userId | id | title       | completed |
  1    | 1  | delectus aut| false     |
  1    | 2  | quis ut     | false     |

I have tried following using lodash , but somehow I feel there us better solution than this, considering the number of loops:

jsonObject = response; // consider the above mention object here.  
keys = _.keys(json[0]); 

Here what I found is that json[0] will not in all case going to be same, so what is the best way to find the solution for this.

Any help will be appreciated!!!

4 Answers 4

2

Inspired from @Akrion's solution, here is the modified version.

Little lengthy solution, but this will help you if:

  1. You have different keys in your JSON data
  2. You have different key sequence in the object
  3. Want to set a default value in case data is not available

const json = [
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut",
    "completed": true
  },
  {
    "completed": false,
    "userId": 1,
    "title": "quis ut",
    "id": 2,
    "extraProp": "test"
  },
];

const headers = Array.from(new Set(json.reduce((acc, cur) =>
  [...acc, ...Object.keys(cur)], [])));

const data = [headers];
const defaultValue = 'NA';

json.forEach(item => {
  data.push(headers.reduce((acc, header) =>
    acc.push(item.hasOwnProperty(header) ? item[header] : defaultValue) && acc, []));
});
console.log(data);

Stackblitz Link: https://stackblitz.com/edit/js-zyh1ps

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

Comments

1

You can also do this in a quite simple way with ES6 and no lodash with Array.reduce:

let data = [{ "userId": 1, "id": 1, "title": "delectus aut", "completed": false }, { "userId": 1, "id": 2, "title": "quis ut", "completed": false } ]

let result = data.reduce((acc,cur) => 
   acc.push(Object.values(cur)) && acc, [Object.keys(data[0])])

console.log(result)

It you set as the initial value of the accumulator the Object.keys array then all you need is to push to that accumulator the Object.values of each iteration in the array. If your header is not always in the first row simply provide it as an array of values etc.

let data = [{ "userId": 1, "id": 1, "title": "delectus aut", "completed": false }, { "userId": 1, "id": 2, "title": "quis ut", "completed": false } ]

let hdr = ["userId", "id", "title", "completed"]
let result = data.reduce((acc,cur) => acc.push(Object.values(cur)) && acc, [hdr])

console.log(result)

Comments

0

First get the header of the table :

let firstObject = array[0];
let header = Object.keys(firstObject);

Now, you have keys in header object.

Use map or forEach on the array and store that in the variable.

let tableValues = table.map((a, i)=>{
    let row = []
    header.forEach((e)=>{row.push(a[e])});
return row;
});

Now you have header and tableValues

header is an array and tableValues is Array of Array

1 Comment

What if some of the data contains extra columns?? array[0] will not going to work in that case
0

Since you want certain columns in a certain order, you should define an array of keys, and the use _.map() and _.pick() to get the values in the correct order from the object. Afterwards, concat the array of values to the array of keys:

const { flow, partialRight: pr, map, at, partial, concat, join } = _

const fn = keys => flow(
  pr(map, o => at(o, keys)),
  partial(concat, [keys]),
)

const keys = ['userId', 'id', 'title', 'completed']

const data = [{"userId":1,"id":1,"title":"delectus aut","completed":false},{"userId":1,"id":2,"title":"quis ut","completed":false}]

const result = fn(keys)(data)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

And the terser lodash/fp version:

const { flow, map, at, concat, join } = _

const fn = keys => flow(
  map(at(keys)),
  concat([keys]),
)

const keys = ['userId', 'id', 'title', 'completed']

const data = [{"userId":1,"id":1,"title":"delectus aut","completed":false},{"userId":1,"id":2,"title":"quis ut","completed":false}]

const result = fn(keys)(data)

console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

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.