I want to check if string is same from an array object or not before sending to a table form, but it can be the same if you didn't change anything in the edit zone. User fill down the table form and send it to the server, next time if user edit the form I want to check if the value are same as the array (which store the previous informations from the table), but it's ok if user didn't change anything but enter to the edit zone. The problem is my code checked that there's no same string but it popup either the true or the false alert message, it popup every message while checking the table form and go into the "false" statement, so I can send nothing after checking string. I will appreciate any help, thx! :)
var arr = [{words: a},{words: b},{words: c},{words: d}];
var val = $('#somethingFromHTML').val()
for(var i = 0; i < arr.length; i++) {
if (arr[i].words.indexOf(val) > -1){
alert("duplicate words")
return false
} else if (arr[i].words.indexOf(val) === -1 || arr[i].words === val){
alert("there's no duplicate words")
return true
}
}
You code always returns the result of checking only arr[0].words, it never moves on to arr[1].words at all, because
You have a return in both of your if blocks, and
Your second if condition is, in part, the inverse of the first one
Consequently, if val is in arr[0].words (indexOf returns > -1), the code will return false. Otherwise, it will return true, because by definition, indexOf returned -1 and your second condition is "if it's -1 or ...". The second part of the or is irrelevant, because the first part will be true.
The minimal change is to put the return true after the loop:
var arr = [{words: a},{words: b},{words: c},{words: d}];
var val = $('#somethingFromHTML').val();
for(var i = 0; i < arr.length; i++) {
if (arr[i].words.indexOf(val) > -1){
alert("duplicate words");
return false;
}
}
alert("there's no duplicate words");
return true;
...but arrays have a feature for just this situation: Array.prototype.some:
var arr = [{words: a},{words: b},{words: c},{words: d}];
var val = $('#somethingFromHTML').val();
if (arr.some(function(entry) { entry.words.indexOf(val) > -1})) {
alert("duplicate words");
return false;
} else {
alert("there's no duplicate words");
return true;
}
some calls its callback repeatedly with the entries in the array, in order, until the callback returns a truthy value. If the callback ever does that, some returns true; if it reaches the end of the array with the callback never having returned a truthy value, it returns false. So it's useful for checking if any entry in the array matches a condition.
Related
Student of The Odin Project Here
https://github.com/TheOdinProject/javascript-exercises/tree/solutions/sumAll
I managed to get the sum part of it work (so it's only the first if statement that is the problem)
They want "ERROR" returned if a non-number is passed as either a or b , or if a or b is a negative number.
I used the code below.
First if statement is evaluating to true even if both a and b are numbers
Their solution was to use !Number.isInteger(a)||!Number.isInteger(b)
Any ideas why the first if statement done as below does not work as intended
If I console.log(a) it logs number
const sumAll = function(a,b) {
let c =0
if((a||b)<0 || (typeof(a)||typeof(b)) !=Number){
return "ERROR"
}
else if(a<b){
for(let i=a; i<=b; i++){
c += i;
}
return c ;
}else if(a>b){for(let i=b; i<=a; i++){
c += i;
}
return c;
}
};
If you want to individually check for a<0 and b<0, you cannot do (a||b)<0. Reason: a||b gets evaluated first and you get the first truthy value out of a and b. So, it becomes a matter of order. If you pass 1,-2 you will get 1 as your result of a||b and obviously 1<0 return false.
function func(a,b){
console.log(a||b);
console.log((a||b)<0);
}
func(1,-2);
func(-1,2);
func(1,2);
Similar problem with (typeof(a)||typeof(b)) !=Number. You are supposed to individually check ((typeof(a) != 'number') || (typeof(b) != 'number')).
Notice how I have changed Number to 'number'. typeof returns a string as mentioned in comments.
You need to amend your if conditions accordingly.
Given is res[]:
for(let k = 0; k < res.length; k++){
if($("#getData").val().length == 20){
//if ((res[k]) != $("#getData").val()) helpText = "No match!";
// -- Tried this too and a several other options - foreach, else, else if e. g.
if(!((res[k]) == $("#getData").val()))
resText = "No match!";
if((res[k]) == $("#getData").val())
resText = "Success!";
$("#result").html(resText);
}
}
If the !((res[k]) == $("#getData").val()) - "false" condition is defined, it always only makes the first res[0] item within the array valid. This item is possible to proof correctly - The array donĀ“t iterate.
If the - "false" condition is not defined, all works fine if only the "true" condition is defined. But in this way there is no resText == "No match!";
What is wrong...?
As #charlietfl mentioned, you are looping across an array and updating the result text at each index. Because you are never stopping the looping process, what this really means is that you are only ever getting the result from the last item in the array. If your "Success!" value is item 14 in a 20 item array, your result will match and pass on that iteration, but then will be overwritten on the iterations for the next 5 items. If the very last item is a success condition you will always get "Success!" and if not you will always get "No match!" regardless of the other items in the list.
My assumption is that what you are looking to do is determine if one of the items in the array is a match, and if so you want "Success!" as the output. If so, I suggest:
const success = false;
const getDataVal = $("#getData").val();
if (getDataVal.length == 20) {
for(let k = 0; k < res.length; k++) {
if (res[k] == getDataVal) {
success = true;
break;
}
}
}
$("#result").html(success ? "Success!" : "No match!");
I restructured your code a bit here to help me understand it. Note that I did some optimizations to it:
Moved the $("#getData").val() operation out of the loop and stored to a variable since the value will not change. This simplifies the code and is much easier on the processor.
Moved the condition on the length check of the value outside the loop. The loop contents would only ever run whenever that condition is true, so it is better to wrap the loop in the condition so that it never runs at all if that condition fails.
Added a break; to the loop to stop the loop once a success condition is found
Moved the setting of the #result outside the loop. This only needs to be done once you know the answer and not at every iteration.
Use a ternary with a simple boolean instead of strings to know the status of the match and output the final string.
If my assumption is correct that you are really interested in knowing if any item in the array matches, then I suggest using the some method of the array to evaluate it. This is a bit more expressive and removes the need for the looping structure.
let success = false;
const getDataVal = $("#getData").val();
if (getDataVal.length == 20) {
success = res.some(function (val)) {
return val == getDataVal;
});
}
$("#result").html(success ? "Success!" : "No match!");
I have an input field where the user inputs their zip code which I then attempt to match to a zip code within an array. While the following works, I need it to actually show an alert dialog once saying that zip code wasn't found, however, it current pops up a lot even if the zip code is in the list.
Here's my snippet:
_zipcodeBtn.onclick = function(){
var userZip = _zipcode.value;
for (var i = 0; i < zipcode_list.length; i++) {
if (zipcode_list[i] === userZip) {
console.log('works');
break;
} else {
alert("repeating");
}
}
};
I want it to check if their zip is available without it also repeating the else statement multiple times. Whats the best way to prevent this?
There's an easier way to find an item in an array, by referencing the array's indexOf() method (docs).
if (zipcode_list.indexOf(userZip) != -1) {
//found - do something
} else
alert('Zip not found!');
As Angel Politis shows, you can also use includes() if you literally just want to know whether an item is in an array, not its actual position within it.
Sidenote: it's important to check against -1 when using indexOf() because it returns the index at which the search is found - or -1 if it's not. If the search is found at the first key, this is 0, and 0 is a falsy value, which can catch people out sometimes when they do things like this:
var arr = [1, 2, 3];
if (arr.indexOf(1))
alert('success');
else
alert('failed');
You'd think the success alert would fire here, but actually it'll be the failure alert, because indexOf() in this case returns 0, and 0 is a falsy value when it's interrogated in a condition.
There's no need to use a loop here. You can just say:
if (!zipcode_list.includes(userZip)) alert("Doesn't work!");
If you must use a loop, then just set a flag by default to false and then, if the zip is found set it to true. Then you can check it outside the loop:
/* Create a flag and set it by default to false. */
var found = false;
/* Loop */
for (var i = 0, l = zipcode_list.length; i < l; i++) {
if (zipcode_list[i] === userZip) {
/* Set the flag to true and stop the loop. */
found = true;
break;
}
}
/* Check whether the zip was found in the array. */
if (found) console.log("Works!");
else alert("Doesn't work!");
I have an array named bars that contains the active id numbers of progress bars. I want to go through this array to find the first value that does not match its index (for finding the lowest available ID). My (apparently incorrect) solution is as follows:
var bars = [0,1];
function getNewBarID(counter) {
var i = counter || 0; //sets i to counter value if it exists, or to 0 if it doesn't
if (bars[i] == i) {
++i;
getNewBarID(i);
} else {
console.log(i);
return i;
}
}
getNewBarID();
When I run this (in a node console and in chrome js console) it logs 2 to the console and returns undefined, while it should return 2.
what!?
edit: when the function is run with an empty array, it both returns and logs 0 (more what!?)
Probably:
return getNewBarID(i);
But to be honest it should rather be:
const newBar = bars.find((el,i) => el !== i) || bars.length; //newBar contains the result...
or a bit longer using a good old for loop:
function getNewBarID(){
let i = 0;
while(bars[i] === i) i++;
return i;
}
Try it
That is because you first run
getNewBarID();
where
if (bars[i] == i)
is true. From there you make the next call, yes, but the first call executes without a return value. You get a return value eventually, however first you executed twice without returning anything. Just add a return to the if-case:
return getNewBarID(i);
I can't seem to quite figure this one out; not sure if I'm even providing a test
condition; Also, "blanks" variable is to hold the value of the elements with the".required" class during the loop.
function containsBlanks(){
var blanks = new Array();
$required.each(function(){
blanks.($(this).val() == "");
});
return(true);
}
Loop over your Nodes and check their value against ""..
function containsBlanks() {
var i, req = $('.required');
for (i = 0; i < req.length; ++i)
if (req[i].value === '')
return true;
return false;
}
If I understand you can do this like:
$('input.required').filter(function(){ return !this.value });
That will give you all required inputs that have an empty value (if any). Then you can check the length property to find out if there are any elements in that collection.