If else in foreach - javascript

I have an array arr=[{key: 'first'},{key: 'second'} ...], I want to go through that array and check if an element with a specific key exist and do something.
arr.forEach(element => {
if(element.key === 'first') {
// do something
} else {
// do something else
}
if(element.key === 'second') {
// do something
} else {
// do something else
}
});
The thing is that when it goes through array, it first sees 'first' and it goes through if() statement, but it also goes through else() statement of 'second' item because it did't find it, and so it does when foreach goes through other items in array. I don't know how to make it to go through array one time and set if() else() appropriately. So when it finds 'first' I want it just to do if() of that item and not else() of others. I hope you understand. Thanks in advance!
Edit: My logic behind this code is that when I call database and find that array if there is no 'firstExercise' in that array, then it should add it to that db (I am using firebase so in else() I am calling db to create that exercise), and if there is'firstExercise' in array do nothing. Sorry for not clarifying that.
Edit2: Here is my original code:
res.forEach(element => {
if (this.numbOfFinished === 1) {
if (element.key === 'firstExercise') {
console.log('has')
} else {
awardName = 'firstExercise'
this.homeService.addAward(this.userId, awardName).then(() => {
this.awardName = 'firstExercise';
this.awarded = true;
});
}
}
});
if (this.numbOfFinished === 5) {
if (element.key === 'fifthExercise') {
console.log('has')
} else {
awardName = 'fifthExercise'
this.homeService.addAward(this.userId, awardName).then(() => {
this.awardName = 'fifthExercise';
this.awarded = true;
});
}
}
});

I personally like to create arrays which makes the relation between a key and functions. So I can iterate and call the proper one.
What I like in this solution instead of using a switch/case or if/else forest is that you can apply automatic treatments and that you can easily make it to evolve.
const mapKeyFunc = [{
key: 'first',
func: async(x) => {
console.log('Do something for key first');
// here you can perform an async request and modify `this`
},
}, {
key: 'second',
func: async(x) => {
console.log('Do something for key second');
// here you can perform an async request and modify `this`
},
}];
const doStuff = async(arr) => {
for (let i = 0; i < arr.length; i += 1) {
const mapElement = mapKeyFunc.find(x => x.key === arr[i].key);
await mapElement.func.call(this, arr[i]);
}
};
const arr = [{
key: 'first',
otherStuff: 0,
}, {
key: 'second',
otherStuff: 42,
}];
doStuff(arr).then(() => {}).catch(e => console.log(e));
If you don't need the treatment to be synchronous, here we have an asynchronous method
const mapKeyFunc = [{
key: 'first',
func: async(x) => {
console.log('Do something for key first');
// here you can perform an async request and modify `this`
},
}, {
key: 'second',
func: async(x) => {
console.log('Do something for key second');
// here you can perform an async request and modify `this`
},
}];
const doStuff = async(arr) => {
await Promise.all(arr.map(x => mapKeyFunc.find(y => y.key === x.key).func.call(this, x)));
};
const arr = [{
key: 'first',
otherStuff: 0,
}, {
key: 'second',
otherStuff: 42,
}];
doStuff(arr).then(() => {}).catch(e => console.log(e));

If you only want one option out of them to be executed (and then exiting out of the function), you could use else if statements like so:
arr.forEach(element => {
if(element.key === 'first') {
// do something
} else if(element.key === 'second') {
// do something
} else {
// do something else
}
});
This will do pretty much exactly what you expect. If element.key == 'first', it'll do block one. Else, if element.key == 'second', it'll do block two. Else, it'll do block three.

You need to merge the if statements like this:
arr.forEach(element => {
if(element.key === 'first') {
// do something
} else if(element.key === 'second') {
// do something else
}
});
element.key has a single value in each iteration and you therefore need a single level of conditioning.

Related

JS is or is not if else

How could I simplify this action below.
I realize this is ridiculous.
But everything I'm trying to do, either one works and one doesn't and vice versa.
I need to send data if this field is not empty. if it is empty, then don't send it: admin|power
it's either null or not
const mreq = await Model.findOne({
where: {
id: req.params.id,
old: req.params.times
}
})
if (!mreq) {
return
} else if (mreq.admin == null) {
return
} else if (mreq.admin) {
res.json(mreq.admin)
} else if (mreq.power == null) {
return
} else if (mreq.power) {
res.json(mreq.power)
}
You don't need all the branches that don't return anything - just test for the two values to be .jsond in two ifs. Use optional chaining to keep things concise.
const mreq = await Model.findOne({ where: { id: req.params.id, old: req.params.times } })
if (mreq?.admin) {
res.json(mreq.admin)
} else if (mreq?.power) {
res.json(mreq.power)
}
Considering that perhaps the property "admin" can be boolean (I don't konw)
You can do something like this:
if(mreq && mreq.admin !== null) {
res.json(mreq.admin);
return;
}
if (mreq.power) { res.json(mreq.power) }
I hope you find it useful.

Filter Object passed on Value Properties

I have an object like this:
let obj = {'machine1':{'err':'404', switch:false},
'gadget1':{'err':'404', switch:true}}
Would not pass validation. => return false
let obj2 = {'machine2':{'err':'404', switch:false},
'gadget2':{'err':null, switch:true}}
Would pass validation. => return true
I want to return true when every key in the object in which the switch is set to true does not have any errors (see obj2). (For machine2 the '404' error does not matter, because the switch is set to false.)
I tried something like that, but didn't get far.
function try() {
for (x in obj) {
obj[x].filter(x=>y.switch === true)
}
}
Thanks for reading!
you could do something like the follow:
const test = obj => Object.keys(obj).every(k => !obj[k].switch || obj[k].err === null)
So you check if every key in the object has switch set to false or the err equal to null.
You can do it by usign entries and every helpers of Array, like this:
let obj = {
'machine1': {
'err': '404',
switch: false
},
'gadget1': {
'err': '404',
switch: true
}
}
let obj2 = {
'machine2': {
'err': '404',
switch: false
},
'gadget2': {
'err': null,
switch: true
}
};
const validate = (data) => {
return Object.entries(data).every(([key, value]) => !value.switch || value.err === null)
}
console.log(validate(obj));
console.log(validate(obj2));
Did you mean something like that?
let obj={
1:{
'machine':{'err':'404', switch:false},
'gadget':{'err':'404', switch:true}
},
2:{
'machine':{'err':'404', switch:false},
'gadget':{'err':null, switch:true}
}
}
I changed the facility a bit to make it easier.
var n=1;
while (n<=2) {
if(obj[n].machine.switch==true){
if(obj[n].machine.err!='404')
console.log('SUKCES')
else console.log('ERROR 1')
}
else console.log('ERROR 0')
if(obj[n].gadget.switch==true){
if(obj[n].gadget.err!='404')
console.log('SUKCES')
else console.log('ERROR 1')
}
else console.log('ERROR 0')
n++;
}
Results:
ERROR 0
ERROR 1
ERROR 0
SUKCES

i wanna return correctly children's object. how can i?

function Ha8(arr, id) {
let result = [];
for(let i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i].children)) {
// if it is a array, it going to be run recursive
result.push(arr[i].children)
const col = Ha8(result[i], id);
if(col === id) {
// find it in array in array
return result
// then return the id object,
} else {
continue; // still can't find.. go ahead!
}
} else if (arr[i]['id']===id) {
return arr[i] // will return valid id object
}
return null // if its none , return null, or parameter id is undefined.
}
}
I m write Intended direction. but its not work..
how can i fix ? give me some tip please.
let input = [
{
id: 1,
name: 'johnny',
},
{
id: 2,
name: 'ingi',
children: [
{
id: 3,
name: 'johnson',
},
{
id: 5,
name: 'steve',
children: [
{
id: 6,
name: 'lisa',
},
],
},
{
id: 11,
},
],
},
{
id: '13',
},
];
output = Ha8(input, 5);
console.log(output); // --> { id: 5, name: 'steve', children: [{ id: 6, name: 'lisa' }] }
output = Ha8(input, 99);
console.log(output); // --> null
I wanna return like that, but only return 'null' ..
need to check children's id and return children's object by using recursive.
so i write like that. but i have no idea..
how to return correctly children id's element?
I will give you an answer using a totally different approach, and using the magic of the JSON.stringify() method, more specifically the replacer optional parameter, which allows the use of a callback function that can be used as a filter.
As you can see, it simplifies a lot the final code. It could also be modified to introduce not only an id, but also any key or value, as I did in my final approach.
EDIT: Following your suggestion, as you prefer your function to be recursive, I recommend you to use the Array.reduce() method. It allows an elegant iteration through all the properties until the needs are met.
Using null as initial value, which is the last argument of the reduce method, it allows to iterate through all fields in the array in the following way:
The first if will always be skipped on the first iteration, as the initial value is null.
The second if will set the currentValue to the accumulator if the property id exists and is equal to the value you are trying to find
The third if, which you could add an Array.isArray() to add a type validation, will check if the property children exists. As it is the last one, it will only work if all the other conditions aren't met. If this property exists, it will call again Ha8Recursive in order to start again the process.
Finally, if neither of this works, it should return null. The absence of this last condition would return undefined if the input id doesn't exist
const Ha8 = (array, inputKey, inputValue) => {
let children = null;
JSON.stringify(array, (key, value) => {
if (value[inputKey] && value[inputKey] === inputValue) {
children = value;
}
return value;
});
return children;
};
const Ha8Recursive = (array, inputKey, inputValue) => {
return array.reduce((accumulator, currentValue) => {
if (accumulator) {
return accumulator;
} else if (currentValue[inputKey] && currentValue[inputKey] === inputValue) {
return currentValue;
} else if (currentValue.children) {
return Ha8Recursive(currentValue.children, inputKey, inputValue);
} else {
return null;
}
}, null)
}
const input = [{"id":1,"name":"johnny"},{"id":2,"name":"ingi","children":[{"id":3,"name":"johnson"},{"id":5,"name":"steve","children":[{"id":6,"name":"lisa"}]},{"id":11}]},{"id":"13"}];
console.log('JSON stringify function');
console.log(Ha8(input, 'id', 5));
console.log('Recursive function')
console.log(Ha8Recursive(input, 'id', 5));

How to Calculate overall status using javascript?

I have 2 Objects in an array with 2 scenarios:
If test_status_id is accepted for all objects in array, then case_status_id should be completed, otherwise case_status_id should be pending. How do I go about doing that?
const result = [{
id:1,
case_status_id : 1(pending),
case_test_map : [{
id:1,
test_status_id: 1(accepted)
},
{
id:2,
test_status_id: 2(rejected)
}]
},
{
id:2,
case_status_id : 2(completed),
case_test_map : [{
id:1,
test_status_id: 1(accepted)
},
{
id:2,
test_status_id: 1(accepted)
}]
}]
Try this
result.forEach(res => {
const resultStatuses = res.case_test_map.map(test => test.test_status_id);
if(resultStatuses.every( (val, i, arr) => val === arr[0] ) ) {
if(resultStatuses[0] === 'accepted') {
res.case_status_id = 'accepted'
}
}
else {
res.case_status_id = 'pending'
}
})
sources:
Check if all values of array are equal
Try the following function, it does what you need:
function calculateCaseStatus(result) {
// at first, iterate over each element of result array
for(let res of result) {
// assume, 'case_status_id' would be set to 2 by default(i.e. 'completed')
let flag = true;
// now, check if any 'test_status_id' is set to 2(i.e. rejected)
// for that, first iterate over each element of 'case_test_map' array
for(let cmp of res.case_test_map) {
if(cmp.test_status_id !== 1) {
// if any test_status_id is not completed, then
// case_status_id can't be 2(i.e. completed)
// so, make the flag false
flag = false;
break;
}
}
// if flag is true, set case_status_id to 2 (i.e. completed)
if(flag) {
res.case_status_id = 2;
} else {
// else set case_status_id to 1 i.e.(pending)
res.case_status_id = 1;
}
}
}
You've to call it like:
calculateCaseStatus(result);
// and to check the result
console.log(result);

Using array.filter down multiple levels

I have a filter function, which uses filter to quickly search a text in an array:
filtered = filtered.filter((row) => {
return Object.keys(row).some((key) => {
return String(row[key]).toLowerCase().indexOf(this.quickSearch.toLowerCase()) > -1
})
})
This works great for single level array, but not sure how to adapt it to work down unknown number of levels of array of objects like this
{
'name': 'james',
'post': {
'name': 'my favorite teams'
}
}
The code above finds james, no problem, but it will not find teams as its not going deep enough.
Naturally I don't want to hardcode something like if row[key] == 'post', because I'm using this code for multiple data sources and need it to be dynamic.
How do I adapt this to work in multi level arrays like the example above?
If there are many levels, then recursion is the best solution:
let searchString = this.quickSearch.toLowerCase(); // do this only once instead of calling toLowerCase over and over again, besides we are using a regular function (not an arrow one) so "this" will be messed up anyways
filtered = filtered.filter(function search(row) { // name the function so we can use recursion (thus we can't use an arrow function)
return Object.keys(row).some((key) => { // ...
if(typeof row[key] === "string") { // if the current property is a string
return row[key].toLowerCase().indexOf(searchString) > -1; // then check if it contains the search string
} else if(row[key] && typeof row[key] === "object") { // oterwise, if it's an object
return search(row[key]); // do a recursive check
}
return false; // return false for any other type (not really necessary as undefined will be returned implicitly)
});
});
You could use a recursive function that calls itself on the values of objects and arrays (using Object.values and Array#some):
const containsDeep = (text) => (value) => {
if(!value) return false;
const valueType = typeof value;
if(valueType === 'string') {
return value.toLowerCase().indexOf(text.toLowerCase()) > -1;
}
if(Array.isArray(value)) {
return value.some(containsDeep(text));
}
if(valueType === 'object') {
return Object.values(value).some(containsDeep(text));
}
return false;
};
const data = [
{
'name': 'bar',
'post': {
'name': 'my favorite teams'
}
},
{
'name': 'fizz',
'posts': [{'name': 'buzz'}]
},
{
'name': 'bla',
'post': {
'name': 'blee',
'comments': [null, {'name': 'bar'}]
}
},
{
'name': 'foo',
'post': {
'name': 'bar'
}
}
];
const result = data.filter(containsDeep('bar'));
console.log(result);

Categories

Resources