JS making a forEach match more efficient - javascript

variants is an object of objects and selectedOptions is an object of option1, option2, option3. The below forEach searches through the variants to find a match.
Is there a more efficient way, using an array method or similar, to do the following:
Object.values(variants).forEach(variant => {
if (variant.options.option1 === selectedOptions.option1 && variant.options.option2 === selectedOptions.option2 && variant.options.option3 === selectedOptions.option3) {
selectedVariant = variant.gid;
}
});

One thing you're doing here is loop through all the variants, overwriting selectedVariant each time you find a match. And if there's supposed to be only one match, you still visit all the other variants when there's no need for it anymore.
More efficient would be:
selectedVariant = Object.values(variants).find(variant => (
variant.options.option1 === selectedOptions.option1 &&
variant.options.option2 === selectedOptions.option2 &&
variant.options.option3 === selectedOptions.option3
)).gid;
That way you stop the moment you find a match.
And to be perfectly honest, setting a variant equal to another variant's gid looks wrong. Either name the variable you assign to selectedVariantGid, or assign the entire variant, and later use the .gid property once you need it. Clear naming is important.

Related

Using 2 conditions with an IF statement in Cypress

Hello I'm trying to run the following code but somehow it does not work. The same code will work if I simply separate the IF statement in 2 and nest it.
My intention is to select only one element from the dropdown list but buy using includes, I'm getting 2 results; that is why I was trying to add an extra condition to it.
cy.get("#autocomplete").type("ne");
cy.get(".ui-menu-item").each(($el) => {
if ($el.text().includes("Netherlands" && $el.text().length === 11)) {
cy.wrap($el).click();
}
Do you happen to know why that is? is there a better way of doing this? thank you
You could do it with a .filter() with a function parameter.
This variation is not currently in the Cypress docs, but they are using jQuery under the hood so refer here jQuery docs, filter(function).
Note the function receives the raw DOM element so use innerText instead of jQuery .text().
You can add multiple criteria, but with === it checks for an exact match and the length check isn't needed.
cy.get("#autocomplete").type("ne");
cy.get('.ui-menu-item') // all items
.filter((index, el) => el.innerText === "Netherlands") // precise match
.eq(0) // take the first
.click(); // select it
There is a ) missing after the text Netherlands, you have to add that and there is an extra bracket ) added after 11, you have to remove that. So, your code should be:
cy.get("#autocomplete").type("ne");
cy.get(".ui-menu-item").each(($el) => {
if ($el.text().includes("Netherlands") && $el.text().length === 11) {
cy.wrap($el).click();
}
I had a somewhat similar issue where I want to select an item in a custom select component (so not a native select element).
I used a derivation of the most upvoted answer to achieve this:
cy.get('my-component .ng-dropdown-panel .ng-option')
.filter((_, el) => {
return el.querySelector('span.badge-location')?.textContent === locationName
&& el.querySelector('span.platform-name')?.textContent === platformName;
})
.should('have.length', 1)
.click();
The code loops through all possible option elements and finds the one I'm looking for and clicks on that one.

Type of this is always object while checking for a valid Javascrip Object

I wrote a Prototype function in javascript to determine whether an entity is a valid Javascript object or not. Something like following
// Check if Object is Valid & Have at least one element
Object.prototype._isValidObject = function () {
return this && typeof this === 'object' && !Array.isArray(this) && Object.keys(this).length >= 1;
};
The problem is it is returning TRUE for most of the values, like even for string, cause this is treated like an object for any value, like arrays, strings or json etc. There may be other ways to do this, but I need to make a prototype function for this. Please determine the correct way to Determine whether a value is a valid Javascript object having atleast one item. Thanks
EDIT
By Valid Javascript / JSON Object I mean something like this:
{
id:100,
name:'somename',
email:'maiL#mail.com'
}
To be more precise following is what I want:
const j = {id:100,name:'somename', email:'maiL#mail.com'};
const s = "{id:100, name:'somename', email:'maiL#mail.com'}";
j._isValidObject(); // Should return true
s._isValidObject(); // Should return false
const j is valid for me cause it is an object having key-value pairs. const s is invalid for me cause it's a string representation of an object, not the object itself. const s can be converted to valid Object like const j, but right now const s is just a string.
EDIT
I have found a solution, and posted it in answers. Though I am not marking it as accepted answer since I'm not sure whether it's the best way to do it. If somebody has a better solution, please post it. Thanks
I have found a solution, though I am not marking as accepted answer since I'm not sure whether it's the best way to do it. If somebody has a better solution, please post it. Thanks
// Check if Object is Valid & Have at least one element
Object.prototype._isValidObject = function () {
return this
&& !(this instanceof String)
&& !Array.isArray(this)
&& Object.keys(this).length >= 1;
};

Check for undefined and length shorter alternatives

I am curious if there are any good and shorter alternatives in modern JS to replace this kind of checks:
if (someVar === undefined || someVar.length === 0) { ... }
The question came from the current work on some obsolete codebase projects.
UPD: I am interested in arrays and strings atm, but would be also nice to compare different types
Your current code looks fine to me, but you can also alternate with the empty array and check its length:
if ((someVar || []).length === 0) {
// ...
}
You could take toString() and check the value for falsyness.
function check(v) {
if (!v || !v.toString()) console.log('empty');
}
check();
check([]);
check('');
So im assuming somVar is an array...
Functional programming is a great way to handle these kinds of things without even having if statements, I dont know what kind of "work" you need to do on the structure but lets assume some filtering mapping and reducing it to a value.
So having a function that will handle the someVar will make sure to handle the undefined case and then it will just be an empty array will will be reduced to a 0.
function handleSomeVar(someVar = []) {
return someVar && someVar
.filter(x => x.something) //lets assume we want to be sure this is defined
.map(x => x.something) // we just want an array of primitives number/string/etc
.reduce((memo, somehthing) => something, 0) //making the assumption that the something is a number.
}
or
const handleSomeVar = (someVar = []) => someVar && someVar
.filter(x => x.something)
.map(x => x.something)
.reduce((memo, something) => something, 0)
implicit return arrow functions are the hardest workers in functional programming (imo)
So then result will be a something, unless someVar is empty and then it will return 0. Reduce is a great way to handle these kinds of instances where things might exist or then might not in the case of nothing well then just return the initial value.
Functional programming in this way is meaningful, debuggable, and lots of fun!

How to Check the variable value is [""] in JavaScript

Example:
When I check a variable containing this value [""] it returns false.
var th=[]
th.push("");
if($("#multiselect").val()==th)
It returns always false.
Thank you.
Edit 1:
changed Var to var. It was a typo.
Edit 2:
Actually, the problem I faced was I was trying to get the value from a multi-select input. The multi-select input sometimes returns values as [""] even I haven't selected any values basically it's a plugin. So I was confused and I thought [""] is a fixed primitive value like 1, 10, "bla blah",.. So I tried to compare it with the same array as the right-hand side of the '=' operator.
It was stupid. Now I posted the solution to my problem and I explained my stupidity.
there are two things:
Change Var to var
You can use includes method of Array as:
var th = [] <==== chnage Var to var
th.push("");
if(th.includes($("#multiselect").val())) { <=== you can use includes method of array
// DO whatever you want
}
Make sure var is lowercased.
You are accessing th as an array, so you’ll need to specify the index of the value you are checking: th[0]
Use triple equals, too: .val()===th[0]
Double check the jquery docs if you’re still running into trouble.
Happy coding!
A couple of things to consider:
You have a typo in the code above; var is valid; Var is invalid.
Browser will aptly complain to solve this typo.
You are comparing an array to DOM value; this will always be false.
DOM is a costly process. Unless the value associated is dynamic, its better to read once, store value into a variable and continue processing instead of reading from DOM always.
You could choose to try something on these lines:
let arr = [1,2,3,4];
let domValue = $("#multiselect").val();
arr.push(5);
arr.map((el, ix) => {
if el === domValue return true; //or choose to do something else here.
});
var th=[]; //It is var not Var
th.push("");
if($("#multiselect").val()==th[0]) // change th to th[0]
I am unable to comment so having to use an answer for now. Are you trying to check if an array has any values? If so you can use
if(th.length){
// do something
}
If you want to check a normal variable for empty string you can simply use
if(th == “”){
//do something
}
I found the solution after a couple of days when I posted this question. Now I can feel how stupid this question was.
Anyway, I'm answering this question so it might help others.
Answer to my question:
When two non-primitive datatype objects(which is the Array here) are compared using an assignment operator, it compares its reference of the object. So the object creation of both arrays would be different. If I want to check the array has [""] value, I should do something like the below.
function isArrValEmptyCheck(value) {
return !value || !(value instanceof Array) || value.length == 0 || value.length == 1 && value[0] == '';
}
console.log(isArrValEmptyCheck([""]));//returns true
console.log(isArrValEmptyCheck(["value1"]));//returns false
Sorry for the late response. Thanks to everyone who tried to help me.

_.findWhere from underscorejs to JQuery

I am trying to implement this code: http://jsfiddle.net/wQysh/351/ in my project.
Everything is fine except for the line:
t = _.findWhere(sc, { id : Number(a.trim()) });
They have used underscorejs and I want to translate this to JQuery without using another lib.
I went through the doc and it stated:
findWhere_.findWhere(list, properties)
Looks through the list and returns the first value that matches all of the key-value pairs listed in properties.
If no match is found, or if list is empty, undefined will be returned.
But still I am confused about this since I am not sure what to return exactly (as first value). Can anyone give me a JQuery alternative to that line?
Thanks in advance..
If you don't the generic nature of _.findWhere() you can use a simple while loop, and compare the id to the numeric value of a (fiddle):
t = 0; // t is used as a counter
aValue = Number(a.trim()); // assign the value to a variable instead of iterating it
while (t < sc.length && sc[t].id !== aValue) { t++; }; // find the index where the id is the as the aValue
t < sc.length && toSet.push(sc[t]); // if t is less the sc.length we found the item in the array
If you need a findWhere without underscore try this gist.
I also used this example in my project. And also needed use JQuery instead of Underscore.
Here is my solution:
t = sc.filter(function (el) { return el.id === a });
It work perfect for me;
If you use number for ids, you can also convert a to integer
t = sc.filter(function (el) { return el.id === parseInt(a, 10) });

Categories

Resources