What is the shorter and faster way to know if a cookie has a value or exists?
I'm using this to know if exists:
document.cookie.indexOf('COOKIENAME=')== -1
This to know if has a value
document.cookie.indexOf('COOKIENAME=VALUE')== -1
Any better? Any problems on this method?
I would suggest writing a little helper function to avoid what zzzzBov mentioned in the comment
The way you use indexOf, it would only evaluate correct if you check for the containment of a String in a cookie, it doesn't match a complete name, in that case the above would return false therefore giving you the wrong result.
function getCookie (name,value) {
if(document.cookie.indexOf(name) == 0) //Match without a ';' if its the firs
return -1<document.cookie.indexOf(value?name+"="+value+";":name+"=")
else if(value && document.cookie.indexOf("; "+name+"="+value) + name.length + value.length + 3== document.cookie.length) //match without an ending ';' if its the last
return true
else { //match cookies in the middle with 2 ';' if you want to check for a value
return -1<document.cookie.indexOf("; "+(value?name+"="+value + ";":name+"="))
}
}
getCookie("utmz") //false
getCookie("__utmz" ) //true
However, this seems to be a bit slow, so giving it an other approach with splitting them
Those are two other possibilities
function getCookie2 (name,value) {
var found = false;
document.cookie.split(";").forEach(function(e) {
var cookie = e.split("=");
if(name == cookie[0].trim() && (!value || value == cookie[1].trim())) {
found = true;
}
})
return found;
}
This one, using the native forEach loop and splitting the cookie array
function getCookie3 (name,value) {
var found = false;
var cookies = document.cookie.split(";");
for (var i = 0,ilen = cookies.length;i<ilen;i++) {
var cookie = cookies[i].split("=");
if(name == cookie[0].trim() && (!value || value == cookie[1].trim())) {
return found=true;
}
}
return found;
};
And this, using an old for loop, which has the advantage of being able to early return the for loop if a cookie is found
Taking a look on JSPerf the last 2 aren't even that slow and only return true if theres really a cookie with the name or value, respectively
I hope you understand what i mean
Apparently:
document.cookie.indexOf("COOKIENAME=VALUE");
For me, is faster, but only slightly.
As the test shows, surprisingly, it's even faster to split the cookie up into arrays first:
document.cookie.split(";").indexOf("COOKIENAME=VALUE");
I use Jquery cookie plugin for this.
<script type="text/javascript" src="jquery.cookie.js"></script>
function isCookieExists(cookiename) {
return (typeof $.cookie(cookiename) !== "undefined");
}
Related
The function is given an array of 2 elements, 2 string to be exact. If the first element has every single letter in the second element (just one time, no case, no order), then the function returns true, if not false.
hey and hello works. But for example, mutation(["zyxwvutsrqponmlkjihgfedcba", "qrstu"]) is not returning true, somehow. I suspect there is something wrong with my if statement nested inside my for loop. Am I returning false or true multiple times, or some other problem?
function mutation(arr) {
var one=arr[0];
var two=arr[1];
one.toLowerCase();
two.toLowerCase();
var array=two.split("");
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) !== -1){
return false;
}else return true;
}
}
mutation(["hello", "hey"]);
EDIT:
New discovery! if I move else return true to right after the end bracket of the for loop, mutation("hello", "neo") would return false, as wanted. But if I did that, then, mutation("hello", "hey") wouldn't return true, whereas before the change, it would.
This:
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) !== -1){
return false;
}else return true;
}
is essentially (close enough) the same as this:
if(one.indexOf(array[0]) !== -1){
return false;
}else return true;
That is, you're not actually looping over anything. Because, no matter what, your loop always returns on the first iteration.
Consider the logic of what your function should do. If I understand correctly, you want to return false if the loop ever encounters a letter that isn't found in one. And to return true if the loop never encounters such a match. In that case, the default condition after the loop would be to return true. Something like this:
for(var i=0;i<array.length;i++){
if(one.indexOf(array[i]) === -1){
return false;
}
}
return true;
Basically, if the loop never found a "non-match", then it never returned false. So return true.
Edit: I also changed the comparison in the if, because I think you had it reversed. But I guess I'm not 100% sure on that, since the intent of the method is a little unclear. (The logic therein is a bit confusing, and the name of the method certainly doesn't help.) But hopefully you at least get the idea and can test/validate accordingly for your needs.
First, you should only return false if you find any character in one that wasn't in two, but you can only return true at the end of the loop, because then you know all characters match. It can't be in the else block.
Second, Shouldn't it be the other way around based on your description? You should iterate the characters of one and see if they are in two instead. Then it would fit.
function mutation(arr) {
var one=arr[0].toLowerCase();
var two=arr[1].toLowerCase();
var oneArr=one.split("");
var twoArr=two.split("");
console.log("Do all of '" + one + "' characters occur in '" + two + "'?");
for(var i=0;i<oneArr.length;i++){
console.log("Looking for " + oneArr[i]);
// If any characters in two didn't occur in one, it fails
var twoIndex = twoArr.indexOf(oneArr[i]);
if(twoIndex === -1) {
console.log("Can't find " + oneArr[i]);
return false;
} else {
console.log("Found at index " + twoIndex + " in '" + two + "'");
}
}
return true;
}
console.log(mutation(["hey", "hello"]));
console.log(mutation(["qrstu", "zyxwvutsrqponmlkjihgfedcba"]));
The main issue is that you're using an else block to return true inside the loop, so your loop is only checking one element then either returning true or false based on whether or not that element is in the first string. Put the return true statement after the for loop.
The second issue is that when you're checking for existence, you're returning false if it does exist. Use one.indexOf(array[i]) === -1 instead.
The final issue is that you're splitting a string to iterate it, but strings don't need to be split to be iterated using a for loop.
The rest of the changes just use less lines of code to do the same thing.
function mutation(arr) {
arr = arr.map(e => e.toLowerCase());
for(let i = arr[1].length - 1; i > -1; --i)
if(arr[0].indexOf(arr[1][i]) === -1) return false;
return true;
}
console.log(mutation(["hello", "hey"]));
console.log(mutation(["hello", "hel"]));
console.log(mutation(["zyxwvutsrqponmlkjihgfedcba", "qrstu"]));
var myStringArray = ["abcd", "efgh", "ijkl"], foundResult = false;
myStringArray.forEach(function(currentString) {
if (/\d+/.test(currentString)) {
console.log("Number found");
foundResult = true;
}
});
if(foundResult === false) {
console.log("Number NOT found");
}
This piece of code is to demonstrate the problem. I have to use an extra variable to check whether there was a match or not. Is there any elegant way to handle this without the variable?
Edit: I know I can use some, but I would like to match the no match case as well as seen in the code's last if condition.
Use some method:
if(["abcd", "efgh", "ijkl"].some(function(i){return /\d+/.test(i)})){
// if matched
} else {
// handle no match
}
An alternative that uses forEach is:
var a = ['abcd', 'efgh', 'ijkl'];
var r;
if (a.forEach(function(a){r = r || /\d/.test(a)}) || r) {
alert('found a number');
} else if (r === false) {
alert('no numbers');
}
but likely any UA that supports forEach will also support some, and some is also probably more efficient as it will stop at the first result of true.
I have found a few posts on here with similar questions but not entirely the same as what I am trying. I am currently using a simple if statement that checks the data the user enters then checks to see if it starts with a number of different values. I am doing this with the following:
var value = string;
var value = value.toLowerCase();
country = "NONE";
county = "NONE";
if (value.indexOf('ba1 ') == 0 || value.indexOf('ba2 ') == 0 || value.indexOf('ba3 ') == 0) { //CHECK AVON (MAINLAND UK) UK.AVON
country = "UK";
county = "UK.AVON";
} else if(value.indexOf('lu') == 0){//CHECK BEDFORDSHIRE (MAINLAND UK) UK.BEDS
country = "UK";
county = "UK.BEDS";
}
I have about 20-30 different if, else statements that are basically checking the post code entered and finding the county associated. However some of these if statements are incredibly long so I would like to store the values inside an array and then in the if statement simply check value.indexOf() for each of the array values.
So in the above example I would have an array as follows for the statement:
var avon = new Array('ba1 ','ba 2','ba3 ');
then inside the indexOf() use each value
Would this be possible with minimal script or am I going to need to make a function for this to work? I am ideally wanting to keep the array inside the if statement instead of querying for each array value.
You can use the some Array method (though you might need to shim it for legacy environments):
var value = string.toLowerCase(),
country = "NONE",
county = "NONE";
if (['ba1 ','ba 2','ba3 '].some(function(str) {
return value.slice(0, str.length) === str;
})) {
country = "UK";
county = "UK.AVON";
}
(using a more performant How to check if a string "StartsWith" another string? implementation also)
For an even shorter condition, you might also resort to regex (anchor and alternation):
if (/^ba(1 | 2|3 )/i.test(string)) { … }
No, it doesn’t exist, but you can make a function to do just that:
function containsAny(string, substrings) {
for(var i = 0; i < substrings.length; i++) {
if(string.indexOf(substrings[i]) !== -1) {
return true;
}
}
return false;
}
Alternatively, there’s a regular expression:
/ba[123] /.test(value)
My recomendation is to rethink your approach and use regular expressions instead of indexOf.
But if you really need it, you can use the following method:
function checkStart(value, acceptableStarts){
for (var i=0; i<acceptableStarts.length; i++) {
if (value.indexOf(acceptableStarts[i]) == 0) {
return true;
}
}
return false;
}
Your previous usage turns into:
if (checkStart(value, ['ba1', ba2 ', 'ba3'])) {
country = 'UK';
}
Even better you can generalize stuff, like this:
var countryPrefixes = {
'UK' : ['ba1','ba2 ', 'ba3'],
'FR' : ['fa2','fa2']
}
for (var key in countryPrefixes) {
if (checkStart(value, countryPrefixes[key]) {
country = key;
}
}
I'd forget using hard-coded logic for this, and just use data:
var countyMapping = {
'BA1': 'UK.AVON',
'BA2': 'UK.AVON',
'BA3': 'UK.AVON',
'LU': 'UK.BEDS',
...
};
Take successive characters off the right hand side of the postcode and do a trivial lookup in the table until you get a match. Four or so lines of code ought to do it:
function getCounty(str) {
while (str.length) {
var res = countyMapping[str];
if (res !== undefined) return res;
str = str.slice(0, -1);
}
}
I'd suggest normalising your strings first to ensure that the space between the two halves of the postcode is present and in the right place.
For extra bonus points, get the table out of a database so you don't have to modify your code when Scotland gets thrown out of leaves the UK ;-)
Well, this is kind of hacky:
function b2n(boo) {
return boo ? 1 : 0;
}
if(b2n(opt1) + b2n(opt2) + b2n(opt3) !== 1) {
throw new Error("Exactly one option must be set");
}
Is there a better way to do this in Javascript? Using any of
more intelligent boolean/number handling
sneaky array or functional operations
And so forth. Javascript and Node solutions welcome.
In my actual problem, the options are coming from the Node module commander, so I'm not dealing with true boolean, just truthy and falsy things. There may be a commander-solution too.
Assuming you had an array of options, you could do:
if(opts.filter(Boolean).length !== 1) {}
It seems to me though that you ought to have one variable with three possible states instead...
var opt = 'a'; // (or 'b', or 'c')
You can do this :
if ( !!opt1 + !!opt2 + !!opt3 !== 1 ) {
It works because
!! makes a boolean from any value (true if the objects evaluates as true in if(value))
when adding booleans you get 1 for true and 0 for false.
You mentioned in your comment that this is coming from a commander options object.
You can do this more elegantly using Lodash:
if (_(options).values().compact().size() === 1)
If you only want to count a subset of the options, you can insert
.pick('a', 'b', 'c')
if ([opt1, opt2, opt3].reduce(function(x, y) { return x + !!y }, 0) == 1) {
// exactly one
};
ECMAScript 5 reduce function.
I think you are being too clever, what's wrong with:
var optionsSelected = 0;
if( opt1 ) optionsSelected++;
if( opt2 ) optionsSelected++;
if( opt3 ) optionsSelected++;
if( optionsSelected !== 1 ) {
throw new Error("Exactly one option must be set");
}
Of course I can play the clever game too:
if( opts.filter(Boolean).length !== 1 ) {
throw new Error("Exactly one option must be set");
}
#spudly is on the right track, but it could be a little more compact:
if( [opt1,opt2,opt3].filter(function(x){return x}).length!==1 ) {
throw new Error("Exactly one option must be set");
}
See ES5's filter method for more information.
I am trying to make an if statement in javascript that will do something if the variable does not equal one of a few different things. I have been trying many different variations of the OR operator, but I cant get it to work.
if(var != "One" || "Two" || "Three"){
// Do Something
}
Any ideas? Thanks!
Update:
I have tried this before:
if(var != "One" || var != "Two" || var != "Three"){
// Do Something
}
For some reason it does not work. My variable is pulling information from the DOM i dont know if that would effect this.
Actual Code
// Gets Value of the Field (Drop Down box)
var itemtype = document.forms[0].elements['itemtype' + i];
if(itemtype.value != "Silverware" || itemtype.value != "Gold Coins" || itemtype.value != "Silver Coins"){
// Do Something
}
Your expression is always true, you need:
if(!(myVar == "One" || myVar == "Two" || myVar == "Three")) {
// myVar is not One, Two or Three
}
Or:
if ((myVar != "One") && (myVar != "Two") && (myVar != "Three")) {
// myVar is not One, Two or Three
}
And, for shortness:
if (!/One|Two|Three/.test(myVar)) {
// myVar is not One, Two or Three
}
// Or:
if (!myVar.match("One|Two|Three")) {
// ...
}
More info:
De Morgan's Laws
Edit: If you go for the last approaches, since the code you posted seems to be part of a loop, I would recommend you to create the regular expression outside the loop, and use the RegExp.prototype.test method rather than String.prototype.match, also you might want to care about word boundaries, i.e. "noOne" will match "One" without them...
Assuming you mean "val does not equal One or Two or Three" then De Morgan's Theorem applies:
if ((val != "One") && (val != "Two") && (val != "Three")) {
// Do something...
}
For a shorter way to do it, try this format (copied from http://snook.ca/archives/javascript/testing_for_a_v):
if(name in {'bobby':'', 'sue':'','smith':''}) { ... }
or
function oc(a)
{
var o = {};
for(var i=0;i<a.length;i++)
{
o[a[i]]='';
}
return o;
}
if( name in oc(['bobby', 'sue','smith']) ) { ... }
The method mentioned by Mike will work fine for just 3 values, but if you want to extend it to n values, your if blocks will rapidly get ugly. Firefox 1.5+ and IE 8 have an Array.indexOf method you can use like so:
if(["One","Two","Test"].indexOf(myVar)!=-1)
{
//do stuff
}
To support this method on IE<=7, you could define a method called Array.hasElement() like so:
Array.prototype.hasElement = function hasElement(someElement)
{
for(var i=0;i<this.length;i++)
{
if(this[i]==someElement)
return true;
}
return false;
}
And then call it like so:
if(!["One","Two","Three"].hasElement(myVar))
{
//do stuff
}
Note: only tested in Firefox, where this works perfectly.
In addition to expanding the expression into three clauses, I think you'd better name your variable something other than var. In JavaScript, var is a keyword. Most browsers aren't going to alert you to this error.
Alternate way using an array:
var selected = ['Silverware', 'Gold Coins', 'Silver Coins'];
if ( selected.indexOf( el.value ) != -1 ) {
// do something if it *was* found in the array of strings.
}
Note: indexOf isnt a native method, grab the snippet here for IE:
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/IndexOf