Find in object to Edit or Add - javascript

I have an object productCounts
[{provisioned=2.0, product=str1, totalID=1.0},
{product=str2, provisioned=4.0, totalID=3.0},
{provisioned=6.0, product=str3, totalID=5.0}]
I have an array uniqueProduct
[str1, str2, str3, str4]
I am then looping a dataset to get the totalID count, add it to the product's totalID but if it doesn't exist, push it to the object.
var countID = 0;
uniqueProduct.forEach(
currentproduct => {
countID = 0;
for (var i = 0; i < shtRng.length; ++i) {
if (shtRng[i][ProductCol].toString() == currentproduct) { // && shtRng[i][IDcol].toString().length>4){
countID++;
}
}
if (countID == 0) {
return;
}
console.log(currentproduct + ": " + countID);
}
)
This works perfectly to return the countID per product in uniqueProduct
Rather than logging the result, I would like to add it to the object like this... If the current unique product is not in the productCounts object, add it.
let obj = productCounts.find((o, i) => {
if (o.product == currentproduct) {
productCounts[i] = { product: currentproduct, totalID: productCounts[i].totalID+countID, provisioned: productCounts[i].provisioned };
return true;
} else {
productCounts.push({ product: currentproduct, totalID: countID, provisioned: 0 });
return true;
}
});
In my head, this should work but it appears to skip some records or add the product multiple times. How do I add to the object correctly?
Expected output is the object to be something similar to:
[{provisioned=2.0, product=str1, totalID=35.0},
{product=str2, provisioned=4.0, totalID=8.0},
{provisioned=6.0, product=str3, totalID=51.0},
{provisioned=6.0, product=str4, totalID=14.0}]

The argument to find() is a function that returns a boolean when the element matches the criteria. The if statement should use the result of this, it shouldn't be in the condition function.
let obj = productCounts.find(o => o.product == currentProduct);
if (obj) {
obj.totalId += countID;
} else {
productCounts.push(productCounts.push({ product: currentproduct, totalID: countID, provisioned: 0 });
}
BTW, your life would be easier if you used an object whose keys are the product names, rather than an array of objects. You can easily turn the array of objects into such an object:
let productCountsObj = Object.fromEntries(productCounts.map(o => [o.product, o]));
if (currentProduct in productCountsObj) {
productCountsObj[currentProduct].totalID += countID;
} else {
productCountsObj[currentProduct] = { product: currentproduct, totalID: countID, provisioned: 0 };
}

Related

How to check specific variable of all array objects

I have an array object with several variables. The objects are created by reading data from firebase.
// Initialize cloud firestore database
let db = firebase.firestore();
//Create a class to store object data
class Data{
constructor(ID,ame, type, location, address, category) {
this.ID = ID;
this.type = type;
this.location = location;
this.address = address;
this.category = category;
}
}
//Get all documents in collection
db.collection("Basic_Data").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
Data_t = new Data(doc.ID,doc.data().type,doc.data().location,doc.data().address,doc.data().category);
all_data.push(Data_t);
});
});
I need to filter the objects based on certain conditions and if multiple filters are selected I need objects that satisfy all the conditions. I have no issues filtering that. After filtering, I try to consolidate values from the different filtering process. But some objects satisfy multiple conditions and are therefore included multiple times (not just twice). Thankfully, every object has a unique ID which I can use to filter the duplicates. But how do I check if an object with the unique ID is already present in the array?
//Filter data by user selection
function dataFilter() {
if ((document.getElementById("filter1-chkBox").checked) || (document.getElementById("filter2-chkBox").checked) || (document.getElementById("filter3-chkBox").checked) || (document.getElementById("filter4-chkBox").checked)) {
if (document.getElementById("filter1-chkBox").checked) {
temp_data_m = all_data.filter(function(info) {
return info.condition1 == true;
});
}
if (document.getElementById("filter2-chkBox").checked) {
temp_data_w = all_data.filter(function(info) {
return info.condition2 == true;
});
}
if (document.getElementById("filter3-chkBox").checked) {
temp_data_d = all_data.filter(function(info) {
return info.condition3 == true;
});
}
if (document.getElementById("filter4-chkBox").checked) {
temp_data_h = all_data.filter(function(info) {
return info.condition4 == true;
});
}
//Consolidate all the filter results
temp_data = temp_data_m;
if (temp_data_m.length != 0) {
temp_data_m = [];
}
if (temp_data_w.length != 0) {
temp_data = temp_data.concat(temp_data_w);
temp_data_w = [];
}
if (temp_data_d.length != 0) {
temp_data = temp_data.concat(temp_data_d);
temp_data_d = [];
}
if (temp_data_h.length != 0) {
temp_data = temp_data.concat(temp_data_h);
temp_data_h = [];
}
//Remove duplicates
temp_data.forEach((info) => {
if (!filtered_data.ID.includes(info.ID)) {
filtered_data.push(info);
}
});
} else {
filtered_data = temp_data;
}
}
I am trying to use forEach() and includes() to remove duplicates but I can't access the variable 'ID' from my array. How do I check the ID of all existing elements in the array?
Did you try to use filter()?
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

Javascript looping through an array : Cannot read property 'slice' of undefined

My api response looks like this:
id: (...)
user_id: (...)
symptoms: "Sore throat, Headache"
id: (...)
user_id: (...)
symptoms: "Anorexia (Loss of appetite), Shortness of breath (Difficult in breathing), Myalgias (Muscle pains), Sore throat, Headache"
I am trying to match a users symptoms to existing symptoms categories. A user can have upto 14 symptoms. I keep getting an error of Cannot read property 'slice' of undefined when i split and slice the array to get individual symptoms and match them.
When i try to put a default value for the object if a user has less than 14 symptoms, the error persists.
My code:
getSymNum (symp, c) {
var counter = 0
for (var xc in c) {
var symp1 = c[xc].symptoms.split(',')[0]
var symp2 = c[xc].symptoms.split(',')[1].slice(1)
var symp3 = c[xc].symptoms.split(',')[2].slice(2)
var symp4 = c[xc].symptoms.split(',')[3].slice(3)
var symp5 = c[xc].symptoms.split(',')[4].slice(4)
var symp6 = c[xc].symptoms.split(',')[5].slice(5)
if (symp3 !== undefined){
console.log("hello ha")
}
if (symp1 === symp) {
counter++
} else if (symp2 === symp) {
counter++
} else if (symp3 === symp) {
counter++
} else if (symp4 === symp) {
counter++
} else if (symp5 === symp) {
counter++
} else if (symp6 === symp) {
counter++
}
}
return counter
},
You can optimize the check by using array/string methods like contains() or indexOf():
etSymNum (symp, c) {
var counter = 0
for (var xc in c) {
if(c[xc].symptoms.indexOf(symp) !== -1){
counter++;
}
}
return counter
},

Swap javascript object index by name

My javascript object looks like the example below, I am wondering how I should write a swap function to change the element position in the object. For example, I want to swap two elements from position 1 to 2 and 2 to 1.
{
element_name_1 : {
//.. data
}
element_name_2 : {
//.. data
}
element_name_3 : {
//.. data
}
element_name_4 : {
//.. data
}
}
Now I want to swap element_name_2 with element_name_1.
As Miles points out, your code is probably broken and should use an array. I wouldn't use it, nor is it tested, but it is possible.
var data = {
element_name_1: {},
element_name_2: {},
element_name_3: {},
element_name_4: {}
}
console.log(data);
var swap = function(object, key1, key2) {
// Get index of the properties
var pos1 = Object.keys(object).findIndex(x => {
return x === key1
});
var pos2 = Object.keys(object).findIndex(x => {
return x === key2
});
// Create new object linearly with the properties swapped
var newObject = {};
Object.keys(data).forEach((key, idx) => {
if (idx === pos1)
newObject[key2] = object[key2];
else if (idx === pos2)
newObject[key1] = object[key1];
else
newObject[key] = object[key];
});
return newObject;
}
console.log(swap(data, "element_name_1", "element_name_2"));
Have a look at the code, may this solve the problem
function swapFunction(source, destination) {
var tempValu,
sourceIndex;
for ( i = 0; i < Arry.length; i++) {
for (var key in Arry[i]) {
Ti.API.info('key : ' + key);
if (source == key) {
tempValu = Arry[i];
sourceIndex = i;
}
if (destination == key) {
Arry[sourceIndex] = Arry[i];
Arry[i] = tempValu;
return Arry;
}
}
}
}
JSON.stringify(swapFunction("key_1", "key_3")); // [{"key_3":"value_3"},{"key_2":"value_2"},{"key_1":"value_1"},{"key_4":"value_4"},{"key_5":"value_5"}]
Let me know if this works.
Good Luck & Cheers
Ashish Sebastian

JavaScript - how do i do the splice of a multidimensional array?

How do i delete the 'test1' from db using the del function?
var db = [];
function add(input) {
for(var key in db) {
if(db[key][0]===input[0]) {
return;
}
}
db[db.length] = input;
}
function edit(input, upgrade) {
for(var key in db) {
if(db[key][0]===input) {
db[key] = upgrade;
}
}
}
function del(input) {
var index = db.indexOf(input);
if (index !== -1) {
db.splice(index, 1);
}
}
add(['test1', 'online']);
console.log(db);
edit('test1', ['test1','offline']);
console.log(db);
del('test1'); // FAILED still shows old values
console.log(db);
The actual problem is not with the splice but with the indexOf. It will return the index of the item, only if the item being searched is the same as the object in the array. So, you have to roll your own search function, like this
function del(input) {
var i;
for (i = 0; i < db.length; i += 1) {
if (db[i][0] === input) {
db.splice(i, 1);
return;
}
}
}
Note: Never iterate an array with for..in. Use normal for loop.

Getting nested obj value

Given the following obj:
var inputMapping = {
nonNestedItem: "someItem here",
sections: {
general: "Some general section information"
}
};
I'm writing a function to get that data by passing in a string "nonNestedItem" or in the nested case "sections.general". I'm having to use an eval and I was wondering if there was maybe a better way to do this.
Here is what I have so far and it works okay. But improve!
function getNode(name) {
var n = name.split(".");
if (n.length === 1) {
n = name[0];
} else {
var isValid = true,
evalStr = 'inputMapping';
for (var i=0;i<n.length;i++) {
evalStr += '["'+ n[i] +'"]';
if (eval(evalStr) === undefined) {
isValid = false;
break;
}
}
if (isValid) {
// Do something like return the value
}
}
}
Linky to Jsbin
You can use Array.prototype.reduce function like this
var accessString = "sections.general";
console.log(accessString.split(".").reduce(function(previous, current) {
return previous[current];
}, inputMapping));
Output
Some general section information
If your environment doesn't support reduce, you can use this recursive version
function getNestedItem(currentObject, listOfKeys) {
if (listOfKeys.length === 0 || !currentObject) {
return currentObject;
}
return getNestedItem(currentObject[listOfKeys[0]], listOfKeys.slice(1));
}
console.log(getNestedItem(inputMapping, "sections.general".split(".")));
You don't need to use eval() here. You can just use [] to get values from an object. Use a temp object to hold the current value, then update it each time you need the next key.
function getNode(mapping, name) {
var n = name.split(".");
if (n.length === 1) {
return mapping[name];
} else {
var tmp = mapping;
for (var i = 0; i < n.length; i++) {
tmp = tmp[n[i]];
}
return tmp;
}
}

Categories