From the below json data how can I check if key "type_1" of "no_2" exists, if doesnt exists to push {"p_id": "24","subcat_id": "2","name": "ok"} to the "type_1" of "no_2" array object.
How does key index and array push works here
{
"no_1": {
"orderNumber": "no_1",
"billing_order_id": "1",
"orderArray": {
"type 2": [
{
"p_id": "25",
"subcat_id": "2",
"name": "fine"
},
{
"p_id": "34",
"subcat_id": "2",
"name": "not ok"
}
]
}
},
"no_2": {
"orderNumber": "no_2",
"billing_order_id": "1",
"orderArray": {
"type_1": [
{
"p_id": "6",
"subcat_id": "1",
"name": "hello"
}
]
}
}
}
I think this is what you're trying to do.
(Most JavaScript code is not structured quite this way, but the sample code is verbose for clarity.)
const
myObj = getObj(),
keyToCheck = "no_3",
myArr = [],
myKeys = Object.keys(myObj), // `.keys` is as static method of Object
keyToPush = myKeys[0], // gets first key in list
valueToPush = myObj[keyToPush], // gets value from this key in obj
fullObjToPush = {}; // makes a new empty object
fullObjToPush[keyToPush] = valueToPush; // Makes a new property in obj w/ key and val
// pushes object to array if `keyToCheck` is not found
if(myKeys.includes(keyToCheck)){ /* do nothing */ }
else{ myArr.push(fullObjToPush); }
// prints result
console.log("myArr now contains this object:");
console.log(myArr);
// provides original object
function getObj(){
return {
"no_1": { "orderNumber": "no_1", "billing_order_id": "1" },
"no_2": { "orderNumber": "no_2", "billing_order_id": "1" }
}
}
Related
how does one go about inserting an item into a nested javascript array of objects (with and without using a library)? running to a problem where once you insert the item after traversing, how would you reassign it back to the original object without manually accessing the object like data.content[0].content[0].content[0] etc..? already tried Iterate through Nested JavaScript Objects but could not get the reassignment to work
const data = {
"content": [
{
"name": "a",
"content": [
{
"name": "b",
"content": [
{
"name": "c",
"content": []
}
]
}
]
}
]
}
inserting {"name": "d", "content": []} into the contents of c
const data = {
"content": [
{
"name": "a",
"content": [
{
"name": "b",
"content": [
{
"name": "c",
"content": [{"name": "d", "content": []}]
}
]
}
]
}
]
}
const data = {
"content": [{
"name": "a",
"content": [{
"name": "b",
"content": [{
"name": "c",
"content": []
}]
}]
}]
}
const insert = createInsert(data)
insert({
"name": "d",
"content": []
}, 'c')
console.log(data)
// create a new function that will be able to insert items to the object
function createInsert(object) {
return function insert(obj, to) {
// create a queue with root data object
const queue = [object]
// while there are elements in the queue
while (queue.length) {
// remove first element from the queue
const current = queue.shift()
// if name of the element is the searched one
if (current.name === to) {
// push the object into the current element and break the loop
current.content.push(obj)
break
}
// add child elements to the queue
for (const item of current.content) {
queue.push(item)
}
}
}
}
It looks like we should assume that the name property uniquely identifies an object in the data structure. With that assumption you could create a mapping object for it, so to map a given name to the corresponding object in the nested structure. Also keep track which is the parent of a given object.
All this meta data can be wrapped in a decorator function, so that the data object gets some capabilities to get, add and remove certain names from it, no matter where it is in the hierarchy:
function mappable(data) {
const map = { "__root__": { content: [] } };
const parent = {};
const dfs = (parentName, obj) => {
parent[obj.name] = parentName;
map[obj.name] = obj;
obj.content?.forEach?.(child => dfs(obj.name, child));
}
Object.defineProperties(data, {
get: { value(name) {
return map[name];
}},
add: { value(parentName, obj) {
this.get(parentName).content.push(obj);
dfs(parentName, obj);
}},
remove: { value(name) {
map[parent[name]].content = map[parent[name]].content.filter(obj =>
obj.name != name
);
delete map[name];
delete parent[name];
}}
});
data.add("__root__", data);
}
// Demo
const data = {"content": [{"name": "a","content": [{"name": "b","content": [{"name": "c","content": []}]}]}]};
mappable(data);
data.add("c", { name: "d", content: [] });
console.log(data);
console.log(data.get("d")); // { name: "d", content: [] }
data.remove("d");
console.log(data.get("d")); // undefined
console.log(data); // original object structure
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 }
});
})
Got an object containing a user id for each user and prices, would like to create a new object/array for each user (no duplicates) and be able to calculate the total sum of price for each user. Tried using Object.values() with map and filter but can't get it to work properly
{
"data": {
"item1": {
"price": "20",
"user": "user1"
},
"item2": {
"price": "10",
"user": "user2"
},
"item3": {
"price": "50",
"user": "user1"
}
}
}
Output something like this:
{
"users": {
"user1": {
"totalSum": "70",
},
"user2": {
"totalSum": "10",
}
}
}
I'm thinking about using map to present the "users"-data, maybe an array would be better?
Using function reduce.
Important: The attribute price is a String, this approach uses object Number to convert that value to a numeric one.
var obj = { "data": { "item1": { "price": "20", "user": "user1" }, "item2": { "price": "10", "user": "user2" }, "item3": { "price": "50", "user": "user1" } }};
var result = Object.keys(obj.data).reduce((a, k) => {
if (a.users[obj.data[k].user]) {
a.users[obj.data[k].user].totalSum += Number(obj.data[k].price);
} else {
a.users[obj.data[k].user] = {
"totalSum": Number(obj.data[k].price)
}
}
return a;
}, {
'users': {}
});
console.log(result);
.as-console-wrapper {
max-height: 100% !important; top: 0;
}
You could leverage ```reduce, more information here
code (haven't tried this)
var data = JSON.parse(mainObj).data;
var usersWithTotalExpenditure = Object.keys(data).reduce(function(result, key) {
var currentItem = data[key];
var useName = currentItem.user;
var price = Number(currentItem.price);
if (userName in result) {
result[userName].totalSum += price;
} else {
result[userName] = {
totalSum: price
};
}
return result;
}, {});
var resultObject = {
users: usersWithTotalExpenditure
}
You can use a forEach loop. This relies on Javascripts powerful OR operator, which coerces the first half of the expression to false if the current user's price is not defined (meaning it is a user the loop hasn't encountered before)
`c is your initial object's data, output is empty object`
const c = obj.data;
var output = {};
Object.keys(c).forEach((val) => {
output[c[val]["user"]] = parseInt(output[c[val]["user"]]) + parseInt(c[val]["price"]) || parseInt(c[val]["price"]);
})
I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')
Trying to push the values into temp Array, from the existing array object. Here am validating whether the values are null or not in my existing object and then pushing it into temp Array.
But currently this is output I am getting : ["0","abc"]
Expected output should be [{"0":"abc"},{"1":"def"}]
Once the values are pushed into the temp array, I need to bind it to my html list.
This is what have tried.
JS:
var tempArray = [];
var json = [
{
"itemId": "1",
"prodTitle": "abc",
},
{
"itemId": "2",
"prodTitle": "def",
},
{
"itemId": "",
"prodTitle": "",
}
]
for (var i=0;i<json.length;i++){
if(json[i].itemId!=""&&json[i].prodTitle!="")
tempArray.itemId = json[i].itemId;
tempArray.prodTitle = json[i].prodTitle;
tempArray.push(tempArray.itemId,tempArray.prodTitle);
}
console.log(tempArray);
Demo URL
You have many mistakes, here's right one
for (var i=0; i<json.length; i++){
if(json[i].itemId && json[i].prodTitle) {
tempArray.push(json[i]);
}
}
Your mistakes
for (var i=0;i<json.length;i++){
if(json[i].itemId!=""&&json[i].prodTitle!="") // <-- mistake, braces are needed, because you have 3 lines below
tempArray.itemId = json[i].itemId; // <-- you are adding property to array
tempArray.prodTitle = json[i].prodTitle; // <-- still adding
tempArray.push(tempArray.itemId,tempArray.prodTitle); //<-- pushing strings, not valid object, use like --> {key: value}
}
Another option using Array.filter Also makes it chain-able. However a for loop will be faster, depends if the chain-ability is something you require, i find it quite powerful at times.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var json = [
{
"itemId": "1",
"prodTitle": "abc",
},
{
"itemId": "2",
"prodTitle": "def",
},
{
"itemId": "",
"prodTitle": "",
}
];
var tempArray = json.filter(function (item) {
return (isDefined(item.itemId) && isDefined(item.prodTitle));
});
function isDefined (o) {
return o !== undefined && o !== null && o !== '';
}
console.log(tempArray);
http://jsfiddle.net/zgg79wfa/1/
You can achieve this without jQuery by using the .filter() method:
var json = [{
"itemId": "1",
"prodTitle": "abc",
},
{
"itemId": "2",
"prodTitle": "def",
},
{
"itemId": "",
"prodTitle": "",
}];
console.log( json );
var tempArray = json.filter( function( el ) {
return el.itemId && el.prodTitle;
});
console.log( tempArray );