for loop breaking out for some reason after array comparison - javascript

I have two arrays, and I'm comparing two values, and then setting a json object:
var compare = ["hh", "pictures", "videos", "aboutMe", "contactMe", "cat", "location"];
var data = ["pictures", "videos", "aboutMe", "contactMe", "cat", "location"];
for (var j=0; j<compare.length; j++) {
if (compare[j] === data[j]) {
self.MenuItems.menu_item[j].added = "added";
}else if (compare[j] !== data[j]){
self.MenuItems.menu_item[j].added = "";
}
}
for some reason, for all self.MenuItems.menu_item[j], they all equal either "added" or "";...

Just so you know this condition is not very efficient, here how it should be
if (compare[j] === data[j]) {
self.MenuItems.menu_item[j].added = "added";
}else {
self.MenuItems.menu_item[j].added = "";
}
and the code does what is intended. Unless you had something else in mind.

Related

How to ignore the loop in else case

I have to compare two values. Both values came from different loops.
if the value is an exact match, I push the array differently.
As you can see in the code. I cant use an "else" after the "if" function because it will literate till the loop stop. I would have multiple pushes.
If I add the array.push after the loop there will be 2 pushes.
for (var prop in obj) {
var array = []
for (var item in obj[prop]) {
for (var i = 0; i < doctyp88.length; i += 1) {
var doctyp88ID = doctyp88[i]._id;
var doctyp88name = doctyp88[i]._source['88_name'];
if (item == doctyp88ID) {
array.push({
"name": item,
"count": obj[prop][item],
"archivname": doctyp88name,
});
}
}
array.push({
"name": item,
"count": obj[prop][item],
});
}
}
What is the best way to avoid my problem?
for (var prop in obj) {
var array = []
for (var item in obj[prop]) {
const newObj = {
"name": item,
}
for (var i = 0; i < doctyp88.length; i += 1) {
var doctyp88ID = doctyp88[i]._id;
var doctyp88name = doctyp88[i]._source['88_name'];
newObj.count= obj[prop][item],
if (item == doctyp88ID) {
newObj.archivname = doctyp88name
}
}
array.push(newObj);
}
}
If I understood your question correctly you could use break [label]; statement to exit from nested loop and skip more pushes but don't exit outside for like this:
loop_1:
for (var prop in obj) {
var array = []
loop_2:
for (var item in obj[prop]) {
loop_3:
for (var i = 0; i < doctyp88.length; i += 1) {
var doctyp88ID = doctyp88[i]._id;
var doctyp88name = doctyp88[i]._source['88_name'];
if (item == doctyp88ID) {
array.push({
"name": item,
"count": obj[prop][item],
"archivname": doctyp88name,
});
break loop_2;
}
}
array.push({
"name": item,
"count": obj[prop][item],
});
}
}

How to count the occurrence of each key within an array of objects?

Say I have an array of objects like so:
[{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}]
I need to count the occurrence of each element and return in it in an array
[3, 0, 1, 2]
any ideas would be appreciated, thanks!
I have attempted
var a = datasets.reduce(function (item, index) {
if (typeof item[index] == 'undefined') {
item[index] = 1;
} else {
item[index] += 1;
}
return item;
}, {});
could not get anything like that to work so i attempted converting it to json and then removing any key: value pairs with no value then counting remaining ones but have had no success with that either
function tableToJson(table) {
var data = [];
var headers = [];
for (var i=0; i < table[0].rows[0].cells.length; i++) {
headers[i] = table[0].rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
}
for (var i=1; i< table[0].rows.length; i++) {
var tableRow = table[0].rows[i];
var rowData = {};
for (var j=0; j<tableRow.cells.length; j++) {
rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
}
data.push(rowData);
}
return data
}
function removeEmpty(jsonObj) {
var newObj = Object.getOwnPropertyNames(jsonObj);
for (var i = 0; i < newObj.length; i++) {
var value = newObj[i];
if (jsonObj[value] === null || jsonObj[value] === undefined) {
delete jsonObj[value];
}
}
}
You can try this
You can do it with reduce().
What i have done is first i check is the object property of current element if it is already in output object. If it's present than i check the value of current element property. if it is true than i increment the property of output object by 1.
If the object property of current element is not available in output than i check for the value of current element property. if it is true i assign output object property with value 1. if false i assign output object property with 0.
let obj = [{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}]
let op = obj.reduce((output,current)=>{
for(let key in current){
if( output[key] ){
if( current[key] ) output[key]+=1;
} else {
if( current[key] ){
output[key] = 1;
} else{
output[key] = 0;
}
}
}
return output;
},{})
console.log(op);
Try this:
var data = [{
taco: "",
burrito: "",
scone: "",
beans: "true"
},
{
taco: "true",
burrito: "",
scone: "true",
beans: ""
},
{
taco: "",
burrito, "true",
scone: "",
beans: "",
}, {
taco: "true",
burrito: "",
scone: "",
beans: "true"
}]
var total = [0, 0, 0, 0];
data.forEach(function(obj) {
if (obj.taco) {
total[0]++;
}
if (burrito) {
total[1]++;
}
if (obj.scone) {
total[2]++;
}
if (obj.beans) {
total[3]++;
}
})
console.log(total)
You can loop through the array and then loop through the keys of each object. Then increment the key of the countObject if it already exists or assign it zero.
This is dynamic. Even if one of the object has an extra key, it will count them. This doesn't expect all the items of array to have the same keys.
var array = [
{"taco":"","burrito":"","scone":"","beans":"true"},
{"taco":"true","burrito":"","scone":"true","beans":""},
{"taco":"true","burrito":"","scone":"","beans":""},
{"taco":"true","burrito":"","scone":"","beans":"true"}
]
var countObject = {};
array.forEach(item => {
Object.keys(item).forEach(key => {
if (item[key] === "true")
countObject[key] = countObject[key] + 1 || 1
else
countObject[key] = countObject[key] || 0
})
})
console.log(countObject); // get the key and count pair
console.log(Object.values(countObject)); // get the counts in an array

How to remove item from an array on condition using JavaScript

I have an an array which is mentioned below. I would like to remove an item from the array which has empty property value using JavaScript.
Actual array:
[
{
"href":"/client",
"methods":[]
},
{
"href":"/home",
"methods":
{
"type1":"GET",
"type2":"POST",
}
},
{
"href":"/about",
"methods":[]
},
{
"href":"/contact",
"methods":
{
"type1":"GET",
"type2":"POST",
}
}
]
Expecting result:
[
{
"href":"/home",
"methods":
{
"type1":"GET",
"type2":"POST",
}
},
{
"href":"/contact",
"methods":
{
"type1":"GET",
"type2":"POST",
}
}
]
This is the job for filter. however filter does not modify the existing array so you need to assign it to a different array/overwrite the current variable
a = a.filter(item => Object.keys(item.methods).length > 0)
Iterate over the object array and filter based on methods property length.
var obj = [...];
obj = obj.filter((val) => val.methods && val.methods.length !== 0);
In the case of methods, you can easily walk the object and then call delete on the keys with values that are empty.... or empty arrays. I expanded the answer to cover not only keys of methods where an array is empty, but all keys with what i would define as empty contents.
var l = [];
for (var i = 0; i < l.length; i++){
var keys = Object.keys(l[i]);
for ( var j = 0; j < keys.length; j++){
var value = keys[j];
// In your use case, you are only doing arrays so i coded it as such.
if (value.length == 0){
delete l[i][j];
}
}
}
If you want to expand it to cover a variety of cases such as empty string, empty arrays, empty maps, or null values you can defined a function to do that.
function isValueDeletable(value){
if (value == null) return true;
if (value == "") return true;
if (value instanceof Array && value.length == 0) return true;
if (value instanceof Map && Object.keys(value).length == 0) return true;
return false;
}
and apply that instead of the value.length == 0;
if (isValueDeletable(value)){ delete l[i][j]; }
Then l is modified to remove all keys with empty values.
enter var json = {};
var key = "giveitakeyvalue";
json[key] = null;
delete json[key];

Comaparing a variable inside a loop

I'm trying to compare for some duplicate value inside a loop because I need to do some logic. My problem is that I can't get the output that I expected.
var tempVal;
for (i = 0; i < obj.length; i++) {
var items = obj[i];
tempVal = items.fund;
console.log(tempVal);
console.log(tempVal == tempVal);
if(tempVal == tempVal){
//do something
}
In my example I have 2 same value in tempVal variable. My console.log(tempVal == tempVal) returns true in first loop but I thought it would return null or undefined in first loop because there's nothing to compare because it's empty on the first loop. What I need is top first return false then true. Thanks
You are comparing the same variable, obviously they are equal, create another variable and compare.
tempVal = items.fund;
console.log(tempVal);
console.log(tempVal == tempVal); //both are same
You haven't defined the initial value. So obuse a variable compare with them self are always equal. Why are you not using another name for remove complexity also.
var tempVal;
for (i = 0; i < obj.length; i++) {
var items = obj[i];
temp = items.fund;
console.log(temp);
console.log(temp == tempVal);
if(temp == tempVal){
//do something
}
Looking at your code, I thought this is what you're trying to achieve:
var src = [
{
"index": 0,
"fund": 100
},
{
"index": 1,
"fund": 200
},
{
"index": 2,
"fund": 100
}];
var tempFunds = [];
const uniqueFunds = src.filter(item => {
if (tempFunds.indexOf(item.fund) === -1) {
tempFunds.push(item.fund);
return item;
}
});
// logs the array with unique funds
console.log(uniqueFunds);
You can implement an else branch above if you want to deal with duplicate fund(s). Although there is no issue with your choice to use a for loop, you could also consider map or filter function(s) based on your problem.

Excel table type standard filter imperfect javascript implementation

So I have a ui pretty much the same as what your find in excel standard filter. (screenshot is arbitrary example unrelated to code examples)
I'm trying to figure out how to evaluate the collection of conditions.
My code checks the condition against the cell and I'm adding a boolean property to show the results of the condition
var filteredData = [];
for (var i = 0; i < data.length; i++) {
var row = data[i];
var rowObj = constructRowObject(
pm, row);
var condResArr = [];
for (var r = 0; r < uiSelectionResultsArr.length; r++) {
var cond = uiSelectionResultsArr[r],
cellValue = rowObj[cond.colName],
expType = cond.expression,
value = cond.value;
if(expType === "equal"){
cond.evaluated = (cellValue == value);
}else if(expType === "not-equal"){
cond.evaluated = (cellValue != value);
}else if(expType === "greater"){
cond.evaluated = (cellValue > value);
}else if(expType === "less"){
cond.evaluated = (cellValue < value);
}
}
//now we have a list of booleans added to our cond objects
//undefined group is the first one (A and D) bracketed by
//adjacent row pairs - therefore sort by id
var sorted = _.sortBy(uiSelectionResultsArr, 'id');
}
So as an example of what I end up with is this
[{
"colName": "id",
"id": 1,
"expression": "greater",
"value": "50",
"evaluated": false
}, {
"colName": "id",
"id": 2,
"expression": "less",
"value": "100",
"operation": "and",
"evaluated": true
}, {
"operation": "or",
"id": 3,
"colName": "id",
"expression": "equal",
"value": "200",
"evaluated": false
}]
Now I need to join the evaluated boolean values by their logical operators ie: the groups they are in - which are implied by the adjacent criteria rows. In this case it would be
if (false && true) || false
This obviously false, but what I'd like to do is build this/whatever the condition expression is at runtime ... is it possible to do such a thing in javascript.
I'm not asking for criticism of the ui or even the logic, I'm just curious if you can "Evaluate an array of boolean values with logical operators at runtime"
My best guess so far is something like this but it has obvious problems.
$("#filter-btn").click( function(e) {
e.preventDefault();
console.log("uiSelectionResultsArr: "+ JSON.stringify(uiSelectionResultsArr));
//order of columns could have been moved can't just use index
var constructRowObject = function(pm, handsonDsRow) {
var colHeaders = pm.currentHeaders;
var newRowObj = {};
for (var index = 0; index < colHeaders.length; index++) {
newRowObj[colHeaders[index]] = handsonDsRow[index];
}
//console.log("constructRowObject: "+ JSON.stringify(newRowObj));
return newRowObj;
};
/*
* [{"operation":"and","id":1,"colName":"id","expression":"equal","value":"500"},
* {"operation":"or","id":2,"colName":"col5","expression":"smaller","value":"100"}]
*/
// the filter in run per table row
// using the condions in
// uiSelectionResultsArr we decide
// if each row should be in the
// results
var data = hot.getData();
var filteredData = [];
for (var i = 0; i < data.length; i++) {
var row = data[i];
var rowObj = constructRowObject(pm, row);
for (var r = 0; r < uiSelectionResultsArr.length; r++) {
var cond = uiSelectionResultsArr[r],
cellValue = rowObj[cond.colName],
expType = cond.expression,
value = cond.value;
if(expType === "equal"){
cond.evaluated = (cellValue == value);
}else if(expType === "not-equal"){
cond.evaluated = (cellValue != value);
}else if(expType === "greater"){
cond.evaluated = (cellValue > value);
}else if(expType === "smaller"){
cond.evaluated = (cellValue < value);
}
}
console.log("uiSelectionResultsArr (after evaluated): "+JSON.stringify(uiSelectionResultsArr));
//now we have a list of booleans added to our cond objects
//undefined group is the first one (A and D) bracketed by
//adjacent row pairs - therefore sort by id
var sorted = _.sortBy(uiSelectionResultsArr, 'id');
//console.log("sorted: "+JSON.stringify(sorted));
/*sorted: [{"colName":"id","id":1,"expression":"greater","value":"50","evaluated":false},
{"colName":"id","id":2,"expression":"smaller","value":"100","operation":"and","evaluated":true},
{"operation":"or","id":3,"colName":"id","expression":"equal","value":"200","evaluated":false}]*/
//if (false && true) || false
//logic is probably wrong but just:
//group by operation
var opgrouped = _.groupBy(uiSelectionResultsArr, 'operation');
//console.log("op grouped: "+JSON.stringify(opgrouped));
//add undefined group to whatever the group the second is in
//there is only ever 1 element in the "undefined" group the top row
if(sorted.length > 1){
if(sorted[1].operation === "and"){
opgrouped.and.push(opgrouped["undefined"][0]);
}else{
opgrouped.or.push(opgrouped["undefined"][0]);
}
}else{//single condition filter in which case just stick it in a new and group
opgrouped.and = [];
opgrouped.and.push(opgrouped["undefined"][0]);
}
//condense each group to single boolean each
var condensedAnd = true, condensedOr = false;
if(opgrouped.and){
for(var x=0;x<opgrouped.and.length;x++){
var cond = opgrouped.and[x];
//console.log("opgrouped.and[x]: where x: "+x+", opgrouped.and[x]: "+JSON.stringify(opgrouped.and[x]));
//console.log("cond.evaluated: "+cond.evaluated);
if(cond.evaluated !== true){
condensedAnd = false;
break;
}
}
}
if(opgrouped.or){
for(var y=0;y<opgrouped.or.length;y++){
var cond = opgrouped.or[y];
if(cond.evaluated === true){
condensedOr = true;
break;
}
}
}
//condense single booleans using or
var result;
if(opgrouped.and && opgrouped.or){
result = (condensedAnd || condensedOr);
}else if(opgrouped.or){
result = condensedOr;
}else if(opgrouped.and){
result = condensedAnd;
}
if(result === true){
console.log("boolean result: "+result+" adding row: "+JSON.stringify(row)+" to filteredData");
filteredData.push(row);
}
//if(i>10)break;//for testing
}
hot.loadData(filteredData);
$.modal.close();
});
This logic works but I can't help feeling it's imperfect maybe someone can offer some suggestions for improvements

Categories

Resources