Javascript: convert JSON object to multiple arrays - javascript

I have an JSON object (hope so?):
[{"label":"label1","value":"value1"}
{"label":"label2","value":"value2"}
{"label":"label3","value":"value3"}]
I want to convert/extract that in 2 arrays like:
var labels = [label1,label2,label3]
var values = [value1,value2,value3]
I have no idea...

Assuming you would like two arrays and there is only ever two properties called label and value in each object, then this would be fine: -
var json_string = '[{"label":"label1", "value":"value1"}, {"label":"label2", "value":"value2"}, {"label":"label3", "value":"value3"}]';
var array = JSON.parse(json_string);
var labels = [];
var values = [];
for (var i = 0; i < array.length; i++) {
labels.push(array[i].label);
values.push(array[i].value);
}
Output: -
console.log(labels); // ["label1", "label2", "label3"]
console.log(values); // ["value1", "value2", "value3"]

You could use the map function to create your results:
var dataObj = [{"label":"label1","value":"value1"},
{"label":"label2","value":"value2"},
{"label":"label3","value":"value3"}];
var labels = dataObj.map(function(obj) {return obj.label;});
var values = dataObj.map(function(obj) {return obj.value;});
I think this solution is more elegant then manually iterating the array.

One other implementation could be;
var dataObj = [{"label":"label1","value":"value1"},
{"label":"label2","value":"value2"},
{"label":"label3","value":"value3"}],
dataStr = JSON.stringify(dataObj),
r = /label":"(\w+).+?value":"(\w+)/g,
m = [],
values = [],
labels = [];
while ((m = r.exec(dataStr)) !== null){
labels.push(m[1]);
values.push(m[2]);
}
console.log(labels, values); // [ 'label1', 'label2', 'label3' ] [ 'value1', 'value2', 'value3' ]

A proposal with one object as result with dynamic keys.
var array = [{ "label": "label1", "value": "value1" }, { "label": "label2", "value": "value2" }, { "label": "label3", "value": "value3" }],
result = {};
array.forEach(function (a) {
['label', 'value'].forEach(function (k) {
result[k] = result[k] || [];
result[k].push(a[k]);
});
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

Related

combine multiple list to single array

{ "data": [ {"firstName": "Achmad"}, {"lastName": "a"} ] } and this my script var body = request.body;for(var i = 0;i < body.data.length;i++){var obj = body.data[i];var keyes = Object.keys(obj);} the problem response from var keyes = Object.keys(obj); is list like this [ 'firstName' ] [ 'lastName' ] i'm wanna like this ['firstName', 'lastName']
Thanks before.
Assuming each of the arrays are elements of a parent array, one way you could achieve this is by using Array.prototype.reduce:
const flat = [
["aku"],
["dia"],
["ia"]
].reduce((accum, el) => accum.concat(el), [])
console.log(flat);
EDITED: You could concat each item of your array :
const body = {
"data": [
{"firstName": "Achmad"},
{"lastName": "a"}
]
};
let result = [];
for (item of body.data) {
result = result.concat(Object.keys(item));
}
console.log(result); // -> ['firstName', 'lastName']
Maybe you want to do something like this
var body = request.body;
var keyes = [];
for(var i = 0; i < body.data.length; i++){
var obj = body.data[i];
keyes.push( Object.keys(obj) );
}

How to remove duplicate names from array of objects

var arr = [
{level:0,name:"greg"},
{level:0,name:"Math"},
{level:0,name:"greg"}
];
I have tried the following:
function removeDuplicates:(dataObject){
self.dataObjectArr = Object.keys(dataObject).map(function(key){
return dataObject[key];
});
for(var i= 0; i < self.dataObjectArr.length; i++ ){
self.dataObjectArr[i]['name'] = self.dataObjectArr[i];
self.uniqArr = new Array();
for(var key in self.dataObjectArr){
self.uniqArr.push(self.dataObjectArr[key]);
}
}
self.uniqObject = DataMixin.toObject(self.uniqArr);
return self.uniqObject;
}
But I get error saying: Uncaught TypeError: Converting circular structure to JSON.
You should push the name to an array or a set and check the same in the following..
var arr = [{
level: 0,
name: "greg"
}, {
level: 0,
name: "Math"
}, {
level: 0,
name: "greg"
}]
function removeDuplicates(arr) {
var temp = []
return arr.filter(function(el) {
if (temp.indexOf(el.name) < 0) {
temp.push(el.name)
return true
}
})
}
console.log(removeDuplicates(arr))
Here's a generic "uniquify" function:
function uniqBy(a, key) {
var seen = new Set();
return a.filter(item => {
var k = key(item);
return !seen.has(k) && seen.add(k)
});
}
///
var arr = [
{level:0,name:"greg"},
{level:0,name:"greg"},
{level:0,name:"joe"},
{level:0,name:Math},
{level:0,name:"greg"},
{level:0,name:"greg"},
{level:0,name:Math},
{level:0,name:"greg"}
];
uniq = uniqBy(arr, x => x.name);
console.log(uniq);
See here for the in-depth discussion.
I believe you have a syntax error " removeDuplicates:(dataObject){ ..."
should be without the ":" >> " removeDuplicates(dataObject){ ... "
"
You can try this :
function removeDuplicates(arr){
var match={}, newArr=[];
for(var i in arr){ if(!match[arr[i].name]){ match[arr[i].name]=1; var newArr=i; } }
return newArr;
}
arr = removeDuplicates(arr);
You can use $.unique(), $.map(), $.grep()
var arr = [
{level:0,name:"greg"},
{level:0,name:"Math"},
{level:0,name:"greg"}
];
var res = $.map($.unique($.map(arr, el => el.name)), name =>
$.grep(arr, el => el.name === name)[0]);
jsfiddle https://jsfiddle.net/4tex8xhy/3
Or you can use such libraries as underscore or lodash (https://lodash.com/docs/4.16.2). Lodash example:
var arr = [
{level:0,name:"greg"},
{level:0,name:"Math"},
{level:0,name:"greg"}
];
var result = _.map(_.keyBy(arr,'name'));
//result will contain
//[
// {
// "level": 0,
// "name": "greg"
// },
// {
// "level": 0,
// "name": "Math"
// }
//]
Ofc. one thing to always consider in these tasks, what do you want exactly are you going to do: modify an existing array, or get a new one back. This example returns you a new array.

Javascript convert array

I have an array of Google Analytics data:
[
["2016-01-01","google","335"],
["2016-01-01","bing","135"],
["2016-01-01","yahoo","35"],
["2016-01-02","google","145"],
["2016-01-02","bing","115"],
...........
]
It can be large. What is the simplest and fastest way to get the following two arrays?
An array of the unique date values:
["2016-01-01","2016-01-02","2016-01-03","2016-01-04"] - this is uniqe sorting date
An array of objects that group the data by source:
[{
source: 'google',
data: [335, 145,.....] // lenght array=count unique date
}, {
source: 'bing',
data: [135, 115,.....]
}, ...
]
A solution with an intermediate object.
var array = [["2016-01-01", "google", "335"], ["2016-01-01", "bing", "135"], ["2016-01-01", "yahoo", "35"], ["2016-01-02", "google", "145"], ["2016-01-02", "bing", "115"]],
object = {},
keys = {},
uniqueData,
grouped = [];
array.forEach(function (a) {
keys[a[0]] = true;
object[a[1]] = object[a[1]] || {};
object[a[1]][a[0]] = a[2];
});
uniqueData = Object.keys(keys).sort();
grouped = Object.keys(object).map(function (k) {
return {
source: k,
data: uniqueData.map(function (a) {
return object[k][a] || 0;
})
};
});
document.write('<pre>' + JSON.stringify(uniqueData, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
a naive implementation:
var arr = [
["2016-01-01","google","335"],
["2016-01-01","bing","135"],
["2016-01-01","yahoo","35"],
["2016-01-02","google","145"],
["2016-01-02","bing","115"],
];
var new_arr = [];
var sources = {};
for(var i = 0; i < arr.length; i++){
if ( sources[arr[i][1]] ){
sources[arr[i][1]].data.push(arr[i][2])
} else {
sources[arr[i][1]] = {
source: arr[i][1],
data: [ arr[i][2] ],
}
}
}
for (var key in sources) {
if (sources.hasOwnProperty(key)) {
new_arr.push(sources[key]);
}
}
console.log(new_arr);
The code above gets you the second array.
The first array should be much simpler to obtain and would be a good exercise for you :)
If you can use lodash, then it is pretty simple:
var data = [
["2016-01-01","google","335"],
["2016-01-01","bing","135"],
["2016-01-01","yahoo","35"],
["2016-01-02","google","145"],
["2016-01-02","bing","115"]
];
var first = _.sortedUniq(data.map(x => x[0]).sort());
var second = _.entries(_.groupBy(data, x => x[1])).map(
e => ({ source: e[0], data: e[1].map(d => d[2]) }) );
logs.innerText = JSON.stringify(first, null, 2) + "\n" + JSON.stringify(second, null, 2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.1/lodash.min.js"></script>
<pre id="logs"></pre>

merging two array of objects with custom compare function with javascript

I have two array of objects like:
var A = [{title:"name1",count:5},{title:"name2",count:1},{title:"name3",count:3}];
and:
var B = [{title:"name2",count:7},{title:"name3",count:2},{title:"name4",count:3},{title:"name5",count:8}];
I need to merge this two array in one array and sum the "count" values in returned array when the "title" properties is same:
the last answer must be:
[{title:"name1",count:5},{title:"name2",count:8},{title:"name3",count:5},{title:"name4",count:3},{title:"name5",count:8}]
how can i do this???
You can use Array#forEach and Array#some to achieve a result
var M = A.concat(B)
var C = [];
M.forEach(function(a) {
var index;
if (C.some(function(c, i) { index = i; return a.title == c.title; })) {
C[index].count += a.count;
} else {
C.push(a);
}
});
console.log(C); // as you expect
Solution with Array.concat and Array.map functions:
var merged = A.concat(B), titles = [], result = [];
merged.map(function(obj){
if (titles.indexOf(obj.title) === -1) {
titles.push(obj.title);
result.push(obj);
} else {
result[titles.indexOf(obj.title)]['count'] += obj['count'];
}
});
console.log(result); // will output the expected array of objects
It can be done like this https://jsfiddle.net/menm9xeo/
var noMatch;
var A = [{title:"name1",count:5},{title:"name2",count:1},{title:"name3",count:3}];
var B = [{title:"name2",count:7},{title:"name3",count:2},{title:"name4",count:3},{title:"name5",count:8}];
//for each A, loop through B's. If a match is found combine the Counts in A.
for(var i=0;i<A.length;i++){
for(var j=0;j<B.length;j++){
if(A[i].title == B[j].title){
A[i].count += B[j].count;
}
}
}
//find all B's that were not combined with A in the previous step, and push them into A.
for(var i=0;i<B.length;i++){
noMatch = true;
for(var j=0;j<A.length;j++){
if(B[i].title == A[j].title){
B[i].count += A[j].count;
noMatch = false;
}
}
if(noMatch){A.push(B[i]);}
}
Heres a simple 3 line answer (minus the A/B vars); utilizes the fact that objects must have unique keys
var A = [{title:"name1",count:5},{title:"name2",count:1},{title:"name3",count:3}];
var B = [{title:"name2",count:7},{title:"name3",count:2},{title:"name4",count:3},{title:"name5",count:8}];
var o = {};
A.concat(B).forEach(function(a){o[a.title] = o.hasOwnProperty(a.title)? o[a.title]+a.count: a.count});
var AB = Object.keys(o).map(function(j){ return {title:j,count:o[j]} });
This proposal is merging and counting with a temporary object and Array#forEach()
The forEach() method executes a provided function once per array element.
var arrayA = [{ title: "name1", count: 5 }, { title: "name2", count: 1 }, { title: "name3", count: 3 }],
arrayB = [{ title: "name2", count: 7 }, { title: "name3", count: 2 }, { title: "name4", count: 3 }, { title: "name5", count: 8 }],
result = function (array) {
var o = {}, r = [];
array.forEach(function (a) {
if (!(a.title in o)) {
o[a.title] = { title: a.title, count: 0 };
r.push(o[a.title]);
}
o[a.title].count += a.count;
});
return r;
}(arrayA.concat(arrayB));
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Using lodash ._concat function :
var result = _.concat(A, B);
Fiddle

Recursive string parsing into object

Hello guys I'm trying to parse an array of strings into a custom structure:
var str = [
"country.UK.level.1",
"country.UK.level.2",
"country.US.level.1",
"country.UK.level.3"
];
Into something like:
var ordered = {
"country": [
{"UK" : {"level" : ["1", "2", "3"]}},
{"US" : {"level" : ["1","2"]}}
]
}
Notes:
Strings stored in the str array will not be sorted and the code should be robust against that.
Strings will follow the x.y.x.y... pattern, where x will be unique for that array and y can change. In my example country and level will always be the same as they represent the x pos.
This requires recursive approach as the strings stored in the str array, can be of any length. The longer the string the deeper nesting.
This should work for you if the last level of your object is an array:
var str = [
"country.UK.level.1",
"country.UK.level.2",
"country.US.level.1",
"country.UK.level.3"
];
var obj = {};
str.forEach(function(str){
var curr = obj;
var splitted = str.split('.');
var last = splitted.pop();
var beforeLast = splitted.pop();
splitted.forEach(function(sub){
if(!curr.hasOwnProperty(sub))
{
curr[sub] = {};
}
curr = curr[sub];
});
if(!curr[beforeLast]){
curr[beforeLast] = [];
}
curr[beforeLast].push(last);
})
console.log(obj);
JSFIDDLE.
This solution utilized a Array.prototype.forEach and Array.prototype.reduce.
var str = [
"country.UK.level.1",
"country.UK.level.2",
"country.US.level.1",
"country.UK.level.3"
],
ordered = {};
str.forEach(function (a) {
var aa = a.split('.'),
val = aa.pop(),
last = aa.length - 1;
aa.reduce(function (obj, pro, i) {
if (!(pro in obj)) {
obj[pro] = i === last ? [] : {};
}
return obj[pro];
}, ordered).push(val);
});
document.write('<pre>' + JSON.stringify(ordered, 0, 4) + '</pre>');

Categories

Resources