Trying to rewrite some code that was very repetitive into some kind of loop, and figuring out the logic is frying my brain somewhat.
The original code looked a bit like this:
if(a){
if(b == "foo1"){
if($('#foo2').val() == a || $('#foo3').val() == a || $('#foo4').val() == a || $('#foo5').val() == a || $('#foo6').val() == a){
//do something here
}
}
}
if(a){
if(b == "foo2"){
if($('#foo1').val() == a || $('#foo3').val() == a || $('#foo4').val() == a || $('#foo5').val() == a || $('#foo6').val() == a){
//do something here
}
}
}
if(a){
if(b == "foo3"){
if($('#foo1').val() == a || $('#foo2').val() == a || $('#foo4').val() == a || $('#foo5').val() == a || $('#foo6').val() == a){
//do something here
}
}
}
if(a){
if(b == "foo4"){
if($('#foo1').val() == a || $('#foo2').val() == a || $('#foo3').val() == a || $('#foo5').val() == a || $('#foo6').val() == a){
//do something here
}
}
}
if(b == "foo5"){
if($('#foo1').val() == a || $('#foo2').val() == a || $('#foo3').val() == a || $('#foo4').val() == a || $('#foo6').val() == a){
//do something here
}
}
}
if(b == "foo6"){
if($('#foo1').val() == a || $('#foo2').val() == a || $('#foo3').val() == a || $('#foo4').val() == a || $('#foo5').val() == a){
//do something here
}
}
}
I want to rewrite this into a loop (or loops), but am struggling to get the logic right.
So far, I have this:
if (a){
for (i=0; i < 6; i++){
var fieldNames =[ "foo1", "foo2", "foo3", "foo4", "foo5", "foo6"]
console.log("i loop "+ fieldNames[i]);
if(b == fieldNames[i]){
for (j = 1; j < fieldNames.length; j++){
if($('#'+fieldNames[j]).val() == a){
//do something here
}
}
}
}
}
I know this isn't right, but can anyone help me with what the logic should be?
Thanks
Edit:
Should clarify what the variables refer to.
This function is called inline from a element on the onblur event with the line doCheck(this.value, 'foo1') (this example relates to just the first instance of that, the b input is foo2 for the second and foo3 for the third and so on...
The full function looks like this:
function doCheck(a,b)
if (a){
for (i=0; i < 6; i++){
var fieldNames =[ "foo1", "foo2", "foo3", "foo4", "foo5", "foo6"]
console.log("i loop "+ fieldNames[i]);
if(b == fieldNames[i]){
for (j = 1; j < fieldNames.length; j++){
if($('#'+fieldNames[j]).val() == a){
//do something here
}
}
}
}
}
}
So the variable a is the value of whatever is in the select element and the b variable is the field name.
You could produce a list of possible fields, remove b from that list, then compare against the remaining ones.
if (a) {
var fieldNames = ['foo1', 'foo2', 'foo3', 'foo4', 'foo5', 'foo6'];
// Remove b from the fields
fieldNames.splice(fieldNames.indexOf(b), 1);
var doSomething = fieldNames.reduce(function(prev, fieldName) {
return prev && $('#' + fieldName).val() === a;
}, true);
if (doSomething) {
// do something
}
}
Another way of looking at this would be something like this:
if (a) {
var fieldNames = ['foo1', 'foo2', 'foo3', 'foo4', 'foo5', 'foo6'];
// Remove b from the fields
fieldNames.splice(fieldNames.indexOf(b), 1);
var doSomething = true;
for (var i = 0; i < fieldNames.length; i++) {
if ($('#' + fieldNames[i]).val() !== a) {
doSomething = false;
break;
}
}
if (doSomething) {
// do something
}
}
I assume that your problem shall be here :
if($('#fieldNames[j]').val() == a){
Repalce with :
if($('#' + fieldNames[j]).val() == a){
Moreover, your loop may be updated like that,
var fieldNames =[ "foo1", "foo2", "foo3", "foo4", "foo5", "foo6"];
// Define fieldNames before the first loop
if (a){
for (i=0; i < fieldNames.length; i++){
console.log("i loop "+ fieldNames[i]);
if(b == fieldNames[i]){
for (j = 1; j < fieldNames.length; j++){ // WHY YOU START AT j=1 ? I shall start at j=0 in my opinion
if($('#fieldNames[j]').val() == a){
//do something here
break; // <=== EXIT 2nd LOOP IF YOU FIND SOMETHING
}
}
}
break; // <=== EXIT 1st LOOP IF YOU FIND SOMETHING
}
}
I am not sure you want the //do something here to be the same for all if blocks in the original code. If you want the same then you can make the loop as you suggest, otherwise not.
Why not put the values i.e. $('#foo2').val() into an array and test for a and b using the indexOf() function on the array?
var fieldValues =[ $("#foo1").val(), $("#foo2").val(), etc];
if(fieldValues.indexOf(a)!=-1 || fieldValues.indexOf(b)!=-1){
//do something here
}
Related
I have the following data:
I basically want the 5,6,7 records to be at the very top of the list ordered by eta. The rest I am OK with as they stand. since they do not realy have an eta.
My JS function :
bubbleSortETA : function(array) {
var swapped;
do {
swapped = false;
for(var i = 0; i < array.length; i++) {
console.log('array[i]');
console.log(array[i]);
console.log('array[i+1]');
console.log(array[i+1]);
var thisRowEta;
var nextRowEta;
if (array[i] && typeof(array[i].eta) != "undefined"){
thisRowEta = array[i].eta;
}else{
thisRowEta = 1000; //so it appears at the bottom???
}
if (array[i+1] && typeof(array[i+1].eta) != "undefined"){
nextRowEta = array[i+1].eta;
}else{
nextRowEta = 1000;
}
if(array[i] && array[i + 1] && typeof(array[i].walkInDetails) != "undefined" && typeof(array[i+1].walkInDetails) != "undefined" && (thisRowEta != nextRowEta)){
this.swap(array, i, i + 1);
console.log('we swapped...');
swapped = true;
}
}
} while(swapped);
console.log(array);
return array;
}
It goes into this never ending loop. I have tried looking at output statements but am unable to understand why it is going into infinite loop.
Any tips?
I'm a javascript beginner doing some CodeWars.com questions. I came across this question and I'm stuck due to a "cannot read property length null" error. I've tried to look up that error and can't find what the problem is in my program.
The assignment is:
"Check to see if a string has the same amount of 'x's and 'o's. The method must return a boolean and be case insensitive. The string can contains any char."
And this is what I've written so far:
function XO(str) {
var x = "x";
var o = "o";
var numX = str.match(/x/gi).length;
var numO = str.match(/o/gi).length;
while(str.indexOf(x) > -1 || str.indexOf(o) > -1) {
if(numX == numO){
return true;
}
}
if (numX === -1 && numO === -1){
return true;
}
}
XO("xoxo");
The assignment also says that if there is neither an X or an O then the program should return true.
This will not give you that error. When there are no matches, the match function returns null and you cannot get the length of null. A few extra lines solves this issue.
function XO(str) {
var x = "x";
var o = "o";
var numX = 0;
var numO = 0;
var xMatch = str.match(/x/gi);
var oMatch = str.match(/o/gi);
if (xMatch) {
numX = xMatch.length;
}
if (oMatch) {
numO = oMatch.length;
}
while(str.indexOf(x) > -1 || str.indexOf(o) > -1) {
if(numX == numO){
return true;
} else {
return false;
}
}
if (numX === -1 && numO === -1){
return true;
} else {
return false;
}
}
console.log(XO("ddd"));
I think you are making this problem more complex than it has to be.
All you need to do is make the string lowercase(to account for case insensitive), traverse the string, and when it finds an x, add 1 to a counter, and when you find and o, decrease 1 from the counter.
If it ends at 0, you return true, else you return false. There's no need for regexes
function XO(str){
var count = 0;
str = str.toLowerCase();
for(var i = 0; i < str.length; i++){
if(str[i] === 'x') count++;
if(str[i] === 'o') count--;
}
return count === 0 ? true : false;
}
Yes you have to check the return value of match is not null before checking the length property. However
while(str.indexOf(x) > -1 || str.indexOf(o) > -1) {
if(numX == numO){
return true;
}
}
looks like an infinite loop if either string contains lower case 'x' or 'o' and there are a different number of each.
More simply:
function XO(str)
{ var matchX = str.match(/x/gi);
var matchY = str.match(/o/gi);
return (matchX && matchY) ? matchX.length == matchY.length : !matchX && !matchY;
}
I have an if statement in javascript that is
if(prop < 0 || trans < 0 || queue < 0 || proc < 0
|| prop > 1 || trans > 1 || queue > 1 || proc > 1
|| prop == "" || trans == "" || queue == "" || proc == ""){
Is there a way to condense this? For prop, trans, queue, and proc. I want to create an if statement if the values do not fall to be between 0 and 1 or if it has an empty string value
Building off of Jordan's answer:
var checkThese = [prop, trans, queue, proc];
var result = checkTruthinessOf(checkThese);
function checkTruthinessOf(things) {
return things.every(function(el) {
return (el < 0 || el > 1 || el === "");
});
}
See Array.prototype.every()
var checkThese = [prop, trans, queue, proc];
var result = checkTruthinessOf(checkThese);
function checkTruthinessOf(things) {
var returnValue = false;
[].forEach.call(things, function(thing){
if (thing < 0 || thing > 1 || thing == "") returnValue = true;
});
return returnValue;
};
I picked up this practice from jQuery. It eliminates the extra array and just passes in as many arguments as you like. Then use rink's function to validate all it at once.
var result = checkTruthinessOf(prop, trans, queue, proc);
function checkTruthinessOf(/*unlimited arguments*/) {
return Array.prototype.every.call(arguments, function(thing) {
return (thing < 0 || thing > 1 || thing === "");
});
}
I want to make condition of if statement dynamically in javascript,
check my code
var t = ['b','a']
if(t[0] !== 'a' && t[1] !== 'a'){console.log('remaining element')}
here t might be vary at any time say t = ['b','a','c'] then I need to write if condition like this
if(t[0] !== 'a' && t[1] !== 'a' && t[2] !== 'a'){console.log('remaining element')}
How can I rewirte this code efficiently?
You can use Array.prototype.every like this
if (t.every(function(currentElement) { return currentElement !== "a"; })) {
console.log('remaining element');
}
This works with arbitrary number of elements.
On older environments which do not support Array.prototype.every, you can use the plain for loop version
var flag = true;
for (var i = 0 ; i < t.length; i += 1) {
if (t[i] === "a") {
flag = false;
break;
}
}
if (flag) {
console.log('remaining element');
}
Mind has gone blank this afternoon and can't for the life of me figure out the right way to do this:
if(i!="3" && i!="4" && i!="5" && i!="6" && i!="7" && i!="8" && i!="9" && i!="2" && i!="19" && i!="18" && i!="60" && i!="61" && i!="50" && i!="49" && i!="79" && i!="78" && i!="81" && i!="82" && i!="80" && i!="70" && i!="90" && i!="91" && i!="92" && i!="93" && i!="94"){
//do stuff
}
All those numbers need to be in an array, then I can check to see if "i" is not equal to any 1 of them.
var a = [3,4,5,6,7,8,9];
if ( a.indexOf( 2 ) == -1 ) {
// do stuff
}
indexOf returns -1 if the number is not found. It returns something other than -1 if it is found. Change your logic if you want.
Wrap the numbers in quotes if you need strings ( a = ['1','2'] ). I don't know what you're dealing with so I made them numbers.
IE and other obscure/older browsers will need the indexOf method:
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
My mind made this solution:
function not(dat, arr) { //"not" function
for(var i=0;i<arr.length;i++) {
if(arr[i] == dat){return false;}
}
return true;
}
var check = [2,3,4,5,6,7,8,9,18,19,49,50,60,61,70,78,79,80,81,82,90,91,92,93,94]; //numbers
if(not(i, check)) {
//do stuff
}
This solution is cross-browser:
var valid = true;
var cantbe = [3, 4, 5]; // Fill in all your values
for (var j in cantbe)
if (typeof cantbe[j] === "number" && i == cantbe[j]){
valid = false;
break;
}
valid will be true if i isn't a 'bad' value, false otherwise.