json array: How to create new array elements? - javascript

My aim is to get a json array like this one:
var args = [{ name: 'test', value: 1 }, { key: 'test2', value: 2}];
How can I get the below code to build up an array like the above one?
this.dependentProperties = []; //array
function addDependentProperty(depName, depValue) {
dependentProperties.push(new Array(depName, depValue));
}
By using the push method I end up having a json notation like this one:
args:{[["test1",1],["test2",2]]}

dependentProperties.push({name: depName, value: depValue});

var args = [{ name: 'test', value: 1 }, { key: 'test2', value: 2}];
...this is an array where each element is a associated-array (=hash, =object).
dependentProperties.push(new Array(depName, depValue));
...you are pushing a (sub-)Array into the parent array. That's not the same as an associative array. You now have a heterogeneous array.
dependentProperties.push({name: depName, value: depValue});
...This is pushing an associated-array into your top-level array. This is what you want. Luca is correct.

newObject = {
"first": "John",
"last": "Doe",
"age": 39,
"sex": "M",
"salary": 70000,
"registered": true,
"interests": [ "Reading", "Mountain Biking", "Hacking" ]
}

var myarray = [];
var myJSON = "";
for (var i = 0; i < 10; i++) {
var item = {
"value": i,
"label": i
};
myarray.push(item);
}
myJSON = JSON.stringify({myarray: myarray});

Related

How to Store Each Object in Loop?

What I would like to do is to process JSON data and store each object after getting out of the for loop. However, the obj gets updated every iteration, so the objectArray holds only David's information in each element in it. I would like the objArray to hold each of the processed JSON objects (screenshot below). The JSON process is to store search a userId and name and store them in the objectArray. Could someone help me figure out how I could store each object in the objectArray? Thank you in advance.
const obj = {};
var objectArray = [];
var data = [
{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId" : "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
]
var dataLen = data.length;
var people = data;
createKeyValue = ((key, value) => {
var temp = {};
temp["value"] = value;
obj[key] = temp;
});
while (dataLen > 0) {
for (let [key, value] of Object.entries(data[0])) {
switch(key) {
case 'userId':
createKeyValue(key, value);
break;
case 'name':
createKeyValue(key, value);
break;
default:
}
}
objectArray.push(obj);
data.shift();
dataLen -= 1;
}
You can do this using a simple forEach() loop to create and push new objects to the objArray array.
const data = [
{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId": "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
];
let objArray = [];
data.forEach(person => {
objArray.push({
userId: { value: person.userId },
name: { value: person.name }
});
});
console.log(objArray);
The error you're seeing is because of a concept in JavaScript (and programming in general) known as "passing by reference."
Objects in JS, instead of being passed as whole groups of data, are passed around as addresses to where that data is stored. This saves a lot of overhead, since objects can become quite large.
In your case however, you're running into one of the ways it can trip you up. Since obj is really getting passed by reference instead of value, you're really .pushing 3 copies of the same address (of obj) onto objectArray rather than 3 distinct sets of data.
A better approach to this problem would be using a JS Array function called map(). This function is probably best explained by MDN:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
You can use it on your data array like this:
var objectArray = [];
var data = [{
"userId": "123",
"name": "John",
"phoneNumber": "123-456-6789"
},
{
"userId": "345",
"name": "Summer",
"phoneNumber": "535-631-9742"
},
{
"userId": "789",
"name": "David",
"phoneNumber": "633-753-1352"
}
]
objectArray = data.map(dataEl => ({
userId: {
value: dataEl.userId,
},
name: {
value: dataEl.name,
},
}));
console.log(objectArray);
.as-console-wrapper {
max-height: 100% !important;
}
As said by our friends Kevin B and Zcoop98, its more appropriate to use forEach function, not map function:
data.forEach(elem => {
objectArray.push({
userId: { value: elem.userId },
name: { value: elem.name }
});
})

Two JS objects, get a value from first object that it missing in the second

I have two JS objects:
var first = [{name: "Sam", group: "test"}, {name: "John", group: "it"}];
var second = [{name: "John", group: "it"}, {name: "Tim", group: "hr"}];
for (var k = 0; k < first.length; k++) {
if (first.indexOf(second[k]) == -1) {
console.log('found');
}
}
I am trying to filter out a value that is present at first, but missing at second. How can I do that?
Ideal return value: {name: "Sam", group: "test"}
Tried many things, nothing works at the moment. For example:
Using Array.filter, we can return items that pass a condition. In this case, the condition is "not in the second list", which we can express with Array.some.
function getItemsOnlyInFirst(first, second) {
return first.filter(
item =>
!second.some(
compareItem =>
item.name === compareItem.name && item.group === compareItem.group
)
);
}
let first = [{ name: "Sam", group: "test" }, { name: "John", group: "it" }];
let second = [{ name: "John", group: "it" }, { name: "Tim", group: "hr" }];
getItemsOnlyInFirst(first, second); // {name: "Sam", group: "test"}
The problem is you cannot compare two objects with the == operator:
var obj1 = {test: 1}
var obj2 = {test: 1}
console.log(obj1 == obj2) // false
An easy solution is to convert the objects into the JSON format.
This works because you can compare strings:
var obj1 = JSON.stringify({test: 1})
var obj2 = JSON.stringify({test: 1})
console.log(obj1 == obj2) // true
Solution using JSON.stringify:
var first = [{name: "Sam", group: "test"}, {name: "John", group: "it"}];
var second = [{name: "John", group: "it"} , {name: "Tim", group: "hr"}];
// Convert the objects to JSON
var second_str = second.map(JSON.stringify)
var filtered = first.filter(function(elem) {
return second_str.indexOf(JSON.stringify(elem)) == -1
})
console.log(filtered)
I understand they both share same interface? For complex objects you could use lodash with eg: _.differenceBy function, but here the case is simple (still, approach is quite generic, does not depends on keys inside objects, but they need to be in flat structure [no recursion])
let isOnlyInFirst = first.filter(el => {
return !second.some(z => {
const el_keys = Object.keys(el)
const z__keys = Object.keys(z)
let flag = true
for (const key of el_keys) {
if (!z.hasOwnProperty(key) || z[key] != el[key]) flag = false
}
if (el_keys.length === z__keys.length && flag)
return true
return false
})
})

How to group an array of objects in JavaScript on specific fields using Lodash?

EDIT:
I believe this is a different problem than a simple _.groupBy because I am trying to group by all keys and returning an hashmap not an array.
I have an array of the following objects:
items = [
{ created_at: "01/01/2016", name: "bob", age: 21, height: 60 },
{ created_at: "01/02/2016", age: 22, height: 70 },
{ created_at: "01/03/2016", name: "alice", age: 23 }
]
And I am trying to transform it into this format:
{
"name": [
{
"value": "bob",
"created_at": "01/01/2016"
},
{
"value": "alice",
"created_at": "01/03/2016"
}
],
"age": [
{
"value": 21,
"created_at": "01/01/2016"
},
{
"value": 22,
"created_at": "01/02/2016"
},
{
"value": 23,
"created_at": "01/03/2016"
}
],
"height": [
{
"value": 60,
"created_at": "01/01/2016"
},
{
"value": 70,
"created_at": "01/02/2016"
}
]
}
My requirement is I am ignoring the created_at field, but grouping everything else.
One solution is:
var items = [
{ created_at: "01/01/2016", name: "bob", age: 21, height: 60 },
{ created_at: "01/02/2016", age: 22, height: 70 },
{ created_at: "01/03/2016", name: "alice", age: 23 }
]
var store = {}
for(var i=0; i < items.length; i++) {
var item = items[i]
for(key in item) {
if(key === "created_at") {
continue
}
value = item[key]
if(!store[key]) {
store[key] = []
}
store[key].push({
value: value,
created_at: item.created_at
})
}
}
$('pre').text(JSON.stringify(store, null, 2))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body><pre></pre></body>
I was wondering if there was some cool way to do it in lodash ... maybe using .map() or .groupBy() or something? I don't quite get how to use them properly and am trying to learn new, more elegant ways to write the code.
You asked specifically about lodash, and so this answer is constructed using lodash.
Note I'm using the _.chain method - this makes it convenient to chain multiple operations rather than running them each separately.
One way (I'm sure there are many others) that gets it pretty close (not perfect) is this:
items = _.chain(items)
.map(function(n) {
var created = _.get(n, 'created_at');
var arr = [];
_.each(n, function(n, k) {
if (k != 'created_at') {
arr.push({
'field': k,
'value': n,
'created_at': created
});
}
});
return arr;
})
.flatten()
.groupBy('field')
.value();
Which results in a collection that looks like this:
{ "name":
[
{ "field": "name", "value": "bob", "created_at": "01/01/2016" },
{ "field": "name", "value": "alice", "created_at": "01/03/2016" }
],
"age": [
....
Here's a Fiddle for playing around with this code.
Using reduce might be the shortest way.
var baseKey = 'created_at';
var result = items.reduce(function(col, item) {
Object.keys(item).forEach(function(key) {
if (key === baseKey || !item[key]) return;
var o = { value: item[key] };
o[baseKey] = item[baseKey];
(col[key] = col[key] || []).push(o);
});
return col;
}, {});
JSFiddle Demo: https://jsfiddle.net/pLcv1am2/6/

How to sum values of objects and push it in an array

I have an array of objects which is dynamic and depend on the selection of rows of a table. An example of it:
var obj = [
{ name: "test1", totalCosts: 45560, actualTotalCosts: 652112, riskCosts: 65442 },
{ name: "test2", totalCosts: 3434, actualTotalCosts: 25252, riskCosts: 34234 },
{ name: "test3", totalCosts: 23123, actualTotalCosts: 23242, riskCosts: 0 },
];
After this array is generated I want to call a function which pushes one more row in this array and names it "total" and sums all the respected values which would look like this:
{name: "total", totalCosts:72117, actualTotalCosts:700606 , risksCosts: 99676 }
obj[0].totalCosts + obj[1].totalCosts + obj[2].totalCosts = obj[3].totalCosts
I tried writing one with my limited knowledge, but that function instead of summing up the values from all three objects, summed up the entire object into one.
function sum1( obj ) {
var result1 = [];
for (var i = 0; i < obj.length; i++) {
var sum = 0, arr = [];
for (var key in obj[i]) {
if (key != 'name') {
sum += obj[i][key];
arr.push(sum[key]);
}
}
result1.push(arr);
return result1;
}
}
Please provide a function which can sum all the objects and return the array with the totals. I also tried using d3.sum but was not successful.
You can take a functional approach with the aid of d3.sum...
obj.push(d3.keys(obj[0]) //get the keys from obj[0]
.reduce(function(sumRow, sumCol) { //construct a summary row
var isNum = !isNaN(obj[0][sumCol]) //only sum numeric fields
return (sumRow[sumCol] = (isNum ? d3.sum(obj, function(row) {
return row[sumCol] //accessor for the column for d3.sum
}) : "All"), sumRow) //append the sum col to the sum row object
},{})); //initial value for reduce is {}
Working example
(function() {
var obj = [{
name: "test1",
name2: "type1",
totalCosts: 45560,
actualTotalCosts: 652112,
riskCosts: 65442
}, {
name: "test2",
name2: "type2",
totalCosts: 3434,
actualTotalCosts: 25252,
riskCosts: 34234
}, {
name: "test3",
name2: "type3",
totalCosts: 23123,
actualTotalCosts: 23242,
riskCosts: 0
}];
obj.push(d3.keys(obj[0])
.reduce(function(sumRow, sumCol) {
var isNum = !isNaN(obj[0][sumCol])
return (sumRow[sumCol] = (isNum ? d3.sum(obj, function(row) {
return row[sumCol]
}) : "All"), sumRow)
}, {}));
d3.select("#result").text(JSON.stringify(obj))
})()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="result"></div>
Note: It's important to realize that what you are calling var obj is actually an array.
That being said, you can iterate over your array and do this:
function sumAll(arr) {
// Create variables for the costs we're tracking
var totalCosts = 0;
var actualTotalCosts = 0;
var riskCosts = 0;
arr.forEach(function(elem) {
// At each iteration of our loop, increase the appropriate variables by their appropriate values
if (elem.hasOwnProperty('totalCosts')) {
totalCosts += elem.totalCosts;
}
if (elem.hasOwnProperty('actualTotalCosts')) {
actualTotalCosts += elem.actualTotalCosts;
}
if (elem.hasOwnProperty('riskCosts')) {
riskCosts += elem.riskCosts
}
});
// Return an object with the information we'd like to have
return {
name: 'total',
totalCosts: totalCosts,
actualTotalCosts: actualTotalCosts,
riskCosts: riskCosts
}
}
From your code:
var obj = [
{ name: "test1", totalCosts: 45560, actualTotalCosts: 652112, riskCosts: 65442 },
{ name: "test2", totalCosts: 3434, actualTotalCosts: 25252, riskCosts: 34234 },
{ name: "test3", totalCosts: 23123, actualTotalCosts: 23242, riskCosts: 0 },
];
Calling my function:
sumAll(obj) // {name: "total", totalCosts: 72117, actualTotalCosts: 700606, riskCosts: 99676}

Javascript push array item to named index

I have a JSON array:
[{ id: 1, client: "Microsoft" },{ id: 2, client: "Microsoft"
},{ id: 3, client: "Apple" }]
and I'd like to group it by "client", but I'm having difficulty with this in javascript. In PHP i'd typically do something like this:
$group = array();
foreach ($array as $item) {
$group[ $item['client'] ] = $item;
}
return $group;
But this method totally wont't work in javascript on a multidimensional array
var group = [];
for ( i=0 ... ) {
var client = array[i].client;
group[ client ].push( array[i] );
}
How would I go about grouping the above array into something like this:
[{ "Microsoft": [{...}], "Apple":[{...}] }]
or even
[{ client: "Microsoft", "items": [{...}] }, { client: "Apple", items: [{...}] }]
You need an object for that, not an array:
var array = [{ id: 1, client: "Microsoft" },{ id: 2, client: "Microsoft" },{ id: 3, client: "Apple" }];
var group = {};
for (var i=0; i<array.length; i++) {
var client = array[i].client;
group[client] = group[client] || []; // create array for client if needed
group[client].push(array[i]);
}
console.log(group);
It's important to keep in mind that the resulting object will contain references to the objects from the original array. For example:
array[0].id = 100;
group.Microsoft[0].id; // 100

Categories