Convert key, values JSON array to tabular JSON format - javascript

I have following JSON data for Chart
var chartJson = [
{
header : '2016',
values : [1, 5, 9]
},
{
header : '2017',
values : [2, 4, 8]
},
{
header : '2018',
values : [3, 1, 5]
}
];
And needs to convert it into this format to feed my HTML table
var tableJson = [
{
2016 : 1,
2017 : 2,
2018 : 3
},
{
2016 : 5,
2017 : 4,
2018 : 1
},
{
2016 : 9,
2017 : 8,
2018 : 5
}
];
Any quick help will be appreciated to convert it into this format.
I tried using this code, but somehow missing on the logic.
let table = [];
for(var row of chartJson ){
for(var value of row.values)
{
table.push(
{
column : row.header,
value : value
});
}
}

var chartJson = [{
header: '2016',
values: [1, 5, 9]
},
{
header: '2017',
values: [2, 4, 8]
},
{
header: '2018',
values: [3, 1, 5]
}
];
let table = [];
chartJson.forEach((row, index) => {
row.values.forEach((val, j) => {
table[j] = { ...table[j],
[row.header]: val
}
});
});
console.log(table)

Iterate through every chartJson's element with its' values(through inner loop) till values' length and make an object from that.
Finally, push that object into the table array.
That's it.
Have a look at the snippet below:
var chartJson = [
{
header: '2016',
values: [1, 5, 9]
},
{
header: '2017',
values: [2, 4, 8]
},
{
header: '2018',
values: [3, 1, 5]
}
];
let table = [];
let len_of_chartJson = chartJson.length, len_of_values = chartJson[0].values.length;
for (var i = 0; i < len_of_chartJson; i++) {
let obj = {};
for (var j = 0; j < len_of_values; j++) {
obj[chartJson[j].header] = chartJson[j].values[i];
}
table.push(obj);
}
console.log(table);

let table = chartJson.reduce((tbl, rec) => {
rec.values.forEach((num, index) => {
if(!tbl[index]){
tbl[index] = {}
}
tbl[index][rec.header] = num
})
return tbl
}, [])
Array reduce function is used to loop through each object, than for each object it loop through each value, checking if the index exist in the table, if it does not exist, it create an empty object at current index. Finally it creates a key value in the current index object.
You read more about reduce function below
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

Related

I want to change the structure of my array

I need to modify a data which is coming from API. The data is coming in the form of array of objects.
const crosses = [
{
fatherLineId: 8,
fatherLineName: "2ART18-0008",
id: 54,
motherLineId: 5,
motherLineName: "2ART18-0005",
},
{
fatherLineId: 3
fatherLineName: "2ART18-0003",
id: 55,
motherLineId: 5,
motherLineName: "2ART18-0005",
}
]
I want my data to be restructured in the form of:
const resultantArr = [
{
enteryNumber: 1,
ParentName: "2ART18-0008"
},
{
entryNumber: 2,
ParentName: "2ART18-0005",
},
{
entryNumber: 3,
ParentName: "2ART18-0003"
},
and so on ...
];
Here the parentName property will have motherLineName values and fatherLineName values in the order.
When you get the result of the api call, loop through it and map the data toy our custom object, I can't provide a complete example based on your question but something like this:
You may also need to parse the apiresult into json using JSON.parse()
var resultantArr = [];
for(var i = 0; i < apiresult.length; i++)
{
resultantArr.push({"enteryNumber" : i + 1 , "ParentName" : apiresult[i].fatherLineName });
}
Loop over the array and push two separate objects into an output array. And keep a record of each object entryname that you increment by two at the end of each iteration.
const crosses=[{fatherLineId:8,fatherLineName:"2ART18-0008",id:54,motherLineId:5,motherLineName:"2ART18-0005"},{fatherLineId:3,fatherLineName:"2ART18-0003",id:55,motherLineId:5,motherLineName:"2ART18-0005"}];
const out = [];
let count = 1;
crosses.forEach(obj => {
const { fatherLineName, motherLineName } = obj;
out.push({
entryNumber: count,
parentName: fatherLineName
});
out.push({
entryNumber: count + 1,
parentName: motherLineName
});
count = count + 2;
});
console.log(out);
Hope it helps you... 🙂
const crosses = [
{
fatherLineId: 8,
fatherLineName: "2ART18-0008",
id: 54,
motherLineId: 5,
motherLineName: "2ART18-0005",
},
{
fatherLineId: 3,
fatherLineName: "2ART18-0003",
id: 55,
motherLineId: 5,
motherLineName: "2ART18-0005",
}
];
var result = [];
var count = 1;
crosses.forEach(cross => {
result.push({
parentName: cross.fatherLineName,
entryNumber: count++,
}),
result.push({ parentName: cross.motherLineName,
entryNumber: count++,
})
});
result

How to filter objects with different keys in array?

I have objects like this one:
{
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
}
and I need to filter through dates object to check if there is specific date and return it's values (ex. if there is 7.01.2020). When I try fro ex user.dates, I get array with 3 different objects but when I use filteror map method, it doesn't work.
When user pick date I need to check if this date exists and add task to the existing ones and if it's new date, add date with tasks...
Any ideas? Thanks!
Actually you need to use for loop if it's not working with filter and map. I would suggest you to access date according to keys from the above arrays
let x = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
}
let y = Object.values(x.dates);
for(const [key,value] of Object.entries(y))
{
//getting particular date string
result = Object.keys(value);
console.log(result);
//converted date for result
date = new Date(result);
console.log(date);
}
please change include your required logic for return date.
I'd probably use a nested loop, where the inner loop is over the properties of the object:
let result = null;
outer: for (const entry of obj.dates) {
for (const [key, value] of Object.entries(entry)) {
if (key === target) {
result = value;
break outer;
}
}
}
Live Example:
const obj = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
};
const target = "7.01.2020";
let result = null;
outer: for (const entry of obj.dates) {
for (const [key, value] of Object.entries(entry)) {
if (key === target) {
result = value;
break outer;
}
}
}
console.log(result);
That makes at most one pass through the data, stopping as soon as it finds a match.
It can be a non-nested loop if you know that the objects in obj.dates only have a single property:
let result = null;
for (const entry of obj.dates) {
const [key] = Object.keys(entry);
if (key === target) {
result = value;
break;
}
}
Live Example:
const obj = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
};
const target = "7.01.2020";
let result = null;
for (const entry of obj.dates) {
const [key] = Object.keys(entry);
if (key === target) {
result = entry[key];
break;
}
}
console.log(result);
Another option would be to turn obj.dates into a Map and then use get on it:
const map = new Map(obj.dates
.map(entry => {
const [key] = Object.keys(entry);
return [key, entry[key]];
})
);
const result = map.get(target);
Live Example:
const obj = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
};
const target = "7.01.2020";
const map = new Map(obj.dates
.map(entry => {
const [key] = Object.keys(entry);
return [key, entry[key]];
})
);
const result = map.get(target);
console.log(result);
That makes a full pass through the data, then a hashed (or similar) lookup on the resulting Map. It's useful if you need to look for multiple targets (since you just build the Map once). Note that this version assumes the objects in obj.dates only have one property.

Javascript Merge/filter array

Given the following json object:
var posts = {
[0] : {
"name": "X",
"categories" : [1, 5, 6]
},
[1] : {
"name": "Y",
"categories" : [1, 5, 7]
}
}
How can I get a single array containing every "categories" property value, without repetitions?
In this case, I would like to retrieve something like
var objCategories = [1, 5, 6, 7];
In a ES6 enabled environment, you can use a Set and reduce
let objCategories = [...new Set(Object.values(posts).reduce((a,b) => a.concat(b.categories), []))];
let posts = {
[0]: {
"name": "X",
"categories": [1, 5, 6]
},
[1]: {
"name": "Y",
"categories": [1, 5, 7]
}
};
let cats = [...new Set(Object.values(posts).reduce((a, b) => a.concat(b.categories), []))];
console.log(cats);
You have to loop through the object:
var posts = {
[0] : {
"name": "X",
"categories" : [1, 5, 6]
},
[1] : {
"name": "Y",
"categories" : [1, 5, 7]
}
}
var objCategories = [];
Object.values(posts).forEach(post => {
post.categories.forEach(c => {
if (objCategories.indexOf(c) === -1) {
objCategories.push(c);
}
})
});
console.log(objCategories);
something like
var objCategories = {}; //create a map for all unique keys
Object.keys(posts).forEach( function(index){
var post = posts[ index ]; //get access to the object
post.categories.forEach( function(cat){
objCategories[ cat ] = cat;
});
});
objCategories = Object.keys( objCategories ); //get only the arrays of categories and assign them back to objCategories for desired result
Use reduce and forEach:
var posts = {
[0] : {
"name": "X",
"categories" : [1, 5, 6]
},
[1] : {
"name": "Y",
"categories" : [1, 5, 7]
}
};
var result = Object.keys(posts).reduce(function (categories, key) {
posts[key].categories.forEach(function (category) {
if (categories.indexOf(category) === -1) {
categories.push(category);
}
});
return categories;
}, []);
console.log(result);
do
var posts = {
[0] : {
"name": "X",
"categories" : [1, 5, 6]
},
[1] : {
"name": "Y",
"categories" : [1, 5, 7]
}
}
// logic
var merged = []; // get all of the categories
for (let name in posts) { // loop through name
var post = posts[name]; // get post
merged = merged.concat(post.categories); // add categories
}
var unique = merged.filter(function(item, pos, self) { // filter duplicates
return self.indexOf(item) == pos;
});
console.log(unique);
exp:
this gathers all the categories
for (let name in posts) { // loop through name
var post = posts[name]; // get post
merged = merged.concat(post.categories); // add categories
}
the result will be
[1, 5, 6, 1, 5, 7]
then this filters out the duplicates:
var unique = merged.filter(function(item, pos, self) { // filter duplicates
return self.indexOf(item) == pos;
});
the result is"
[1, 5, 6, 7]

How to convert a nested object into an array of objects?

inputJson = {
"mn": {
"mt1": 1,
"mtop": 2,
"ot1": 3
},
"ln": {
"mt1": 4,
"mtop": 5,
"ot1": 6
}
}
OutputArrayOfJson=[
{ rs: "mt1", mn: 1, ln: 4 },
{ rs: "mtop", mn: 2, ln: 5 },
{ rs: "ot1", mn: 3, ln: 6 }
]
rs is hardcode Key.
I don't know why am having hard time doing this operation.
It is a conversion of javascript objects
inputJson = {
"mn": {
"mt1": 1,
"mtop": 2,
"ot1": 3
},
"ln": {
"mt1": 4,
"mtop": 5,
"ot1": 6
}
}
d = {};
for(var key1 in inputJson){
for(var key2 in inputJson[key1]) {
if(!(key2 in d)){
d[key2]={};
}
d[key2][key1] = inputJson[key1][key2];
}
}
v = [];
for(var k in d){
var o = {};
o.rs=k;
for(var k2 in d[k]){
o[k2] = d[k][k2];
}
v.push(o);
}
//result is in v
note: the next time you should shown example code or not will help
You can iterate through the object and push each root property inside an array:
var arr = [];
for (var p in inputJson){
arr.push(inputJson[p]);
}
console.log(arr);

Grouping consecutive elements together using Javascript

I have an array of elements like so:
messages[i], where messages[i] may only exist for certain values of i. For instance messages[0] and messages[2] may exist but not messages[1].
Now I would like to group together elements with continuous indices, for example if the indices for which messages existed were:
2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20
I would like to group them like so:
2, 3, 4, 5
8, 9
12, 13, 14, 15, 16, 17
20
What would be an effective way to do so using Javascript?
EDIT:
for (i = 0; i < messages.length; i++) {
if (messages[i].from_user_id == current_user_id) {
// group the continuous messages together
} else {
//group these continuous messages together
}
}
You can use a counter variable which has to be incremented and the difference between the index and the consecutive elements are the same, group them in a temporary array. If the difference is varies for two consecutive array elements, the temporary element has to be moved to the result and the temporary array has to be assigned a new array object.
var array = [2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20];
var result = [], temp = [], difference;
for (var i = 0; i < array.length; i += 1) {
if (difference !== (array[i] - i)) {
if (difference !== undefined) {
result.push(temp);
temp = [];
}
difference = array[i] - i;
}
temp.push(array[i]);
}
if (temp.length) {
result.push(temp);
}
console.log(result);
# [ [ 2, 3, 4, 5 ], [ 8, 9 ], [ 12, 13, 14, 15, 16, 17 ], [ 20 ] ]
Given :
var data = [ undefined, undefined, 2, 3, 4, 5,
undefined,undefined, 8, 9,
undefined, undefined, 12, 13, 14, 15, 16, 17,
undefined, undefined, 20];
(or the almost equivalent array where the undefined elements don't exist at all, but where the defined elements have the same indices as above) this reduce call will return a two-dimensional array where each top level element is the contents of the original array, grouped by contiguously defined entries:
var r = data.reduce(function(a, b, i, v) {
if (b !== undefined) { // ignore undefined entries
if (v[i - 1] === undefined) { // if this is the start of a new run
a.push([]); // then create a new subarray
}
a[a.length - 1].push(b); // append current value to subarray
}
return a; // return state for next iteration
}, []); // initial top-level array
i.e. [[ 2, 3, 4, 5], [8, 9], [12, 13, 14, 15, 16, 17], [20]]
NB: this could also be written using a .forEach call, but I like .reduce because it requires no temporary variables - all state is encapsulated in the function parameters.
I would iterate through the list, and if you find an element at messages[i], add i to a list of mins. Then, once you don't find an element at messages[j], and j to a list of maxes.
Then you will have two lists (or one, if you use a container, as I probably would) that contains the start and stop indexes of the groups.
Another approach would be something like this. I'm using a library called lodash for my array manipulation.
Basically I'm sorting the array in ascending order. And then for every increment, I'm storing the current element to a temporary array and comparing the last value of that array to the current element if they are in sequence if not I push the values of the temporary array to my result array and so on. If my loop reaches the end I just push the values of my temporary array to my results array.
var _ = require('lodash');
var arr = [2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20];
arr = _.sortBy(arr, function (o) {
return o;
});
var tmp = [];
var res = [];
for (var i = 0; i < arr.length; i++) {
if (tmp.length === 0) {
tmp.push(arr[i]);
}
else {
var lastEl = _.last(tmp);
if ((lastEl + 1) === arr[i]) {
tmp.push(arr[i]);
}
else {
res.push(tmp);
tmp = [];
tmp.push(arr[i]);
}
if (i === (arr.length - 1)) {
res.push(tmp);
tmp = [];
}
}
}
// Outputs: [ [ 2, 3, 4, 5 ], [ 8, 9 ], [ 12, 13, 14, 15, 16, 17 ], [ 20 ] ]
const cluster = (arr, tmp = [], result = []) =>
(result = arr.reduce((acc, c, i) =>
(!tmp.length || c === (arr[i-1]+1)
? (tmp.push(c), acc)
: (acc.push(tmp), tmp = [c], acc))
, []), tmp.length ? (result.push(tmp), result) : result)
console.log(cluster([2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20]))

Categories