I have JS array with strings, for example:
var strArray = [ "q", "w", "w", "e", "i", "u", "r"];
I need to compare for duplicate strings inside array, and if duplicate string exists, there should be alert box pointing to that string.
I was trying to compare it with for loop, but I don't know how to write code so that array checks its own strings for duplicates, without already pre-determined string to compare.
The findDuplicates function (below) compares index of all items in array with index of first occurrence of same item. If indexes are not same returns it as duplicate.
let strArray = [ "q", "w", "w", "w", "e", "i", "u", "r"];
let findDuplicates = arr => arr.filter((item, index) => arr.indexOf(item) != index)
console.log(findDuplicates(strArray)) // All duplicates
console.log([...new Set(findDuplicates(strArray))]) // Unique duplicates
Using ES6 features
Because each value in the Set has to be unique, the value equality will be checked.
function checkIfDuplicateExists(arr) {
return new Set(arr).size !== arr.length
}
var arr = ["a", "a", "b", "c"];
var arr1 = ["a", "b", "c"];
console.log(checkIfDuplicateExists(arr)); // true
console.log(checkIfDuplicateExists(arr1)); // false
var strArray = [ "q", "w", "w", "e", "i", "u", "r", "q"];
var alreadySeen = {};
strArray.forEach(function(str) {
if (alreadySeen[str])
console.log(str);
else
alreadySeen[str] = true;
});
I added another duplicate in there from your original just to show it would find a non-consecutive duplicate.
Updated version with arrow function:
const strArray = [ "q", "w", "w", "e", "i", "u", "r", "q"];
const alreadySeen = {};
strArray.forEach(str => alreadySeen[str] ? console.log(str) : alreadySeen[str] = true);
You could take a Set and filter to the values that have already been seen.
var array = ["q", "w", "w", "e", "i", "u", "r"],
seen = array.filter((s => v => s.has(v) || !s.add(v))(new Set));
console.log(seen);
Using some function on arrays:
If any item in the array has an index number from the beginning is not equals to index number from the end, then this item exists in the array more than once.
// vanilla js
function hasDuplicates(arr) {
return arr.some( function(item) {
return arr.indexOf(item) !== arr.lastIndexOf(item);
});
}
function hasDuplicates(arr) {
var counts = [];
for (var i = 0; i <= arr.length; i++) {
if (counts[arr[i]] === undefined) {
counts[arr[i]] = 1;
} else {
return true;
}
}
return false;
}
// [...]
var arr = [1, 1, 2, 3, 4];
if (hasDuplicates(arr)) {
alert('Error: you have duplicates values !')
}
Simple Javascript (if you don't know ES6)
function hasDuplicates(arr) {
var counts = [];
for (var i = 0; i <= arr.length; i++) {
if (counts[arr[i]] === undefined) {
counts[arr[i]] = 1;
} else {
return true;
}
}
return false;
}
// [...]
var arr = [1, 1, 2, 3, 4];
if (hasDuplicates(arr)) {
alert('Error: you have duplicates values !')
}
function hasDuplicateString(strings: string[]): boolean {
const table: { [key: string]: boolean} = {}
for (let string of strings) {
if (string in table) return true;
table[string] = true;
}
return false
}
Here the in operator is generally considered to be an 0(1) time lookup, since it's a hash table lookup.
var elems = ['f', 'a','b','f', 'c','d','e','f','c'];
elems.sort();
elems.forEach(function (value, index, arr){
let first_index = arr.indexOf(value);
let last_index = arr.lastIndexOf(value);
if(first_index !== last_index){
console.log('Duplicate item in array ' + value);
}else{
console.log('unique items in array ' + value);
}
});
You have to create an empty array then check each element of the given array if the new array already has the element it will alert you.
Something like this.
var strArray = [ "q", "w", "w", "e", "i", "u", "r"];
let newArray =[];
function check(arr){
for(let elements of arr){
if(newArray.includes(elements)){
alert(elements)
}
else{
newArray.push(elements);
}
}
return newArray.sort();
}
check(strArray);
Use object keys for good performance when you work with a big array (in that case, loop for each element and loop again to check duplicate will be very slowly).
var strArray = ["q", "w", "w", "e", "i", "u", "r"];
var counting = {};
strArray.forEach(function (str) {
counting[str] = (counting[str] || 0) + 1;
});
if (Object.keys(counting).length !== strArray.length) {
console.log("Has duplicates");
var str;
for (str in counting) {
if (counting.hasOwnProperty(str)) {
if (counting[str] > 1) {
console.log(str + " appears " + counting[str] + " times");
}
}
}
}
This is the simplest solution I guess :
function diffArray(arr1, arr2) {
return arr1
.concat(arr2)
.filter(item => !arr1.includes(item) || !arr2.includes(item));
}
const isDuplicate = (str) =>{
return new Set(str.split("")).size === str.length;
}
You could use reduce:
const arr = ["q", "w", "w", "e", "i", "u", "r"]
arr.reduce((acc, cur) => {
if(acc[cur]) {
acc.duplicates.push(cur)
} else {
acc[cur] = true //anything could go here
}
}, { duplicates: [] })
Result would look like this:
{ ...Non Duplicate Values, duplicates: ["w"] }
That way you can do whatever you want with the duplicate values!
Related
Im trying to learn forEach() method but i cant find more advanced examples. So i thought about refactoring my Codewars code to learn from it. I dont know know to properly use forEach method in nested loops. Hope You can help me learn from this example :)
6 kyu - Replace With Alphabet Position
https://www.codewars.com/kata/546f922b54af40e1e90001da/train/javascript
function alphabetPosition(text) {
let textToArray = text.replace(/[^a-zA-Z]/gi,'').toUpperCase().split(''); //Eliminate anything thats not a letter
const alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
let pointsHolder = []; //empty array for score
for (let i = 0; i < textToArray.length; i++){
for (let j = 0; j < alphabet.length; j++) {
if (textToArray[i] == alphabet[j] ) { //We check the index of given string letter in alphabet
pointsHolder.push(j+1) //give it a score based on place in alphabet(+1 for 0 as 1st index)
}
}
}
return pointsHolder.join(' '); //return scored array as a string with spaces
}
There is really no need to use a nested loop, which is computationally expensive. With that, you also don't have to manually create an A-Z array.
You can easily convert alphabets to any arbitrary number using String.charCodeAt(). a has a character code of 97, b has a character code of 98, and etc... to get a one-based index (a=1, b=2, ...) you jus t need to subtract 96 from the number.
function alphabetPosition(text) {
const alphabets = text.toLowerCase().replace(/[^a-z]/g, '').split('');
return alphabets.map(alphabet => alphabet.charCodeAt(0) - 96).join(' ');
}
Alternatively you can also use a for...of loop, but that requires storing the array in yet another variable before returning it:
function alphabetPosition(text) {
const alphabets = text.toLowerCase().replace(/[^a-z]/g, '');
const codes = [];
for (const alphabet of alphabets) {
codes.push(alphabet.charCodeAt() - 96);
}
return codes.join(' ');
}
(Note: #Terry's solution is still the more efficient solution to your code challenge)
You can replace it in the following way:
function alphabetPosition(text) {
let textToArray = text.replace(/[^a-zA-Z]/gi, '').toUpperCase().split('');
const alphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
let pointsHolder = [];
textToArray.forEach(t2a => {
alphabet.forEach((a, j) => {
if (t2a == a) { pointsHolder.push(j + 1) }
})
})
return pointsHolder.join(' ');
}
console.log(alphabetPosition("ABCSTU"))
An alternative to the charCode solution proposed in Terry's answer but which also avoids nested loops is be to create a Map of the characters you want to score against and then access it per character from the passed string.
Keep in mind that strings are iterable without needing to convert to an array.
function alphabetPosition(text) {
text = text.toUpperCase().replace(/[^A-Z]/gi, '');
const alphabet = new Map(
["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
.map((v, i) => [v, i + 1])
);
const pointsHolder = [];
for (const char of text) {
pointsHolder.push(alphabet.get(char))
}
return pointsHolder.join(' ');
}
console.log(alphabetPosition("AB😬CS🐹TU"))
This also allows you to use a Map which doesn't necessarily have consecutive charCodes
function alphabetPosition(text) {
text = text.toUpperCase().replace(/[^😬🐹🤓]/gi, '');
const alphabet = new Map(
["😬", "🐹", "🤓"]
.map((v, i) => [v, i + 1])
);
const pointsHolder = [];
for (const char of text) {
pointsHolder.push(alphabet.get(char))
}
return pointsHolder.join(' ');
}
console.log(alphabetPosition("AB😬CS🐹TU"))
Given an array of strings, I'd like to check for opposite directions and cancel them out (remove them from the array) and return a new array.
For example:
let arr = ["N", "E", "W", "S", "W", "S", "N", "W"]
should reduce to:
newArr = ["W", "W"]
Here is what I have come up with so far. I am getting undefined and I am not sure why.
let arr = ["N", "E", "W", "S", "W", "S", "N", "W"]
function checkForOpposites(arr) {
let nOpp = ["N", "S"]
let sOpp = ["S", "N"]
let eOpp = ["E", "W"]
let wOpp = ["W", "E"]
for (var i = 0; i < arr.length; i++) {
if (arr[i] + arr[i + 1] === nOpp)
if (arr[i] + arr[i + 1] === sOpp)
if (arr[i] + arr[i + 1] === eOpp)
if (arr[i] + arr[i + 1] === wOpp) {
return true
}
}
}
function newDirections(arr) {
arr.filter(checkForOpposites)
}
You could filter the array until the length is not changing.
let
array = ["N", "E", "W", "S", "W", "S", "N", "W"],
temp;
do {
let index = -1;
temp = array;
array = temp.filter((v, i, { [i + 1]: next }) => {
if (i === index) return false;
if (
v === 'N' && next === 'S' || v === 'S' && next === 'N' ||
v === 'E' && next === 'W' || v === 'W' && next === 'E'
) {
index = i + 1;
return false;
}
return true;
});
} while (temp.length !== array.length)
console.log(array);
function cancelDirections(array) {
var ncnt = 0, ecnt = 0, scnt = 0, wcnt = 0;
var output = "";
for (var n of array) {
switch (n) {
case "N":
ncnt++;
break;
case "E":
ecnt++;
break;
case "S":
scnt++;
break;
case "W":
wcnt++;
break;
}
}
if (ecnt > wcnt) { ecnt -= wcnt; wcnt = 0;}
else { wcnt -= ecnt; ecnt = 0}
if (ncnt > scnt) { ncnt -= scnt; scnt = 0; }
else { scnt -= ncnt; ncnt = 0; }
return output + "N".repeat(ncnt) + "S".repeat(scnt) + "E".repeat(ecnt) + "W".repeat(wcnt);
}
let arr = ["N", "E", "W", "S", "W", "S", "N", "W"]
console.log(cancelDirections(arr))
Explanation:
I keep track of the count of each element, and then just cancel them out. This approach is O(n); I would be interested if there was a faster way.
First issue is you get undefined because you are not returning anything
function newDirections(arr) { arr.filter(checkForOpposites) } // <-- no return so undefined
Second issue is your logic is wrong and your code is basically saying everything would have to be equal which is not possible. Your code looks like this:
if (arr[i] + arr[i + 1] === nOpp) {
if (arr[i] + arr[i + 1] === sOpp) {
if (arr[i] + arr[i + 1] === eOpp) {
if (arr[i] + arr[i + 1] === wOpp) {
return true;
}
}
}
}
Next you are using filter which loops multiple times and then you are looping inside of it. Filter is not the way to go. You want to do something with a loop.
var opposites = {
N: 'S',
S: 'N',
E: 'W',
W: 'E',
};
function newDirections(orgArr) {
// in case you want original cloning array
var arr = orgArr.slice();
// loop from start to 2nd to last element in array
var i = 0;
while (i < arr.length - 1) {
// grab current and next direction
var dir = arr[i];
var nextDir = arr[i + 1];
// check to see if they are opposite
if (opposites[dir] === nextDir) {
// remove them
arr.splice(i, 2); // index and 2 items
// if we are not at the start move back one position so we can check the new direction
if (i > 0) {
i--;
}
} else {
// if not opposite move forward
i++;
}
}
return arr;
}
const arr = ["N", "E", "W", "S", "W", "S", "N", "W"];
console.log(newDirections(arr));
console.log(newDirections(["N", "S", "E", "W", "W", "S"]));
console.log(newDirections(["E", "N", "S", "E", "W", "W", "S"]));
console.log(newDirections(["E", "E", "W", "N", "S", "E", "W", "W"]));
You can map the directions to vectors, sum the vectors and reduce the resulting vector to a list of directions.
var arr = ["N", "E", "W", "S", "W", "S", "N", "W"]
var vecMap = {
N: [1,0],
E: [0,1],
S: [-1,0],
W: [0,-1]
};
var revMap = [
['N','S'],
['E','W']
];
const dir2Vec = dir => vecMap[dir];
const vec2Dir = (acc, cur, i) => {
//get the direction based on the reverse map.
const dir = revMap[i][+(cur < 0)];
//array with n items where n is the length of the vector
const dup = Array.from({length: Math.abs(cur)}).fill(dir);
return [...acc, ...dup]
}
const sumVec = (a,b) => [a[0]+b[0], a[1]+b[1]];
const res = arr
.map(dir2Vec)
.reduce(sumVec)
.reduce(vec2Dir, [])
console.log(res)
First of all, you cannot compare arrays like this if (arr[i] + arr[i + 1] === nOpp). In this case, === will compare if both sides of the comparison are Array type objects, and if they are the same object, not if their content is the same, for that you should use other ways.
Open node.js CLI and paste this code
const nOpp = ["N", "S"];
console.log(nOpp === ["N", "S"]);
and you'll see false printed in the console.
For a more detailed explanation, look here: How to compare arrays in JavaScript?
Second, nesting if like this is equivalent to successive ANDs
if (arr[i] + arr[i + 1] === nOpp)
if (arr[i] + arr[i + 1] === sOpp)
if (arr[i] + arr[i + 1] === eOpp)
if (arr[i] + arr[i + 1] === wOpp) {
...
}
This means that only if the first if evaluates to true the second one will be evaluated if this evaluates to true the third will be evaluated, and so on.
Now, that all being said, here is my version.
I just took into account the first paragraph of your question, and the desired result, then came to this:
let arr = ["N", "E", "W", "S", "W", "S", "N", "W"]
const opposites = [
["N", "S"],
["W", "E"],
];
const checkForOpposites = data => {
const result = [];
data.forEach((v0, i, a) => {
let oppositeFound = false;
opposites.forEach(o => {
if (v0 != a[i+1] && o.includes(v0) && o.includes(a[i+1])) {
oppositeFound = true
result.push(i, i+1);
}
});
// console.log(`${i} => ${v0} | ${i+1} => ${a[i+1]} | ${oppositeFound}`);
});
return result;
}
const cleanOpposites = data => {
let result = data;
let n = [];
do {
n = checkForOpposites(result);
// console.log(n);
if (n.length > 0) {
result = result.reduce((accum, curr, i) => {
if (!n.includes(i)) {
accum.push(curr);
}
return accum;
}, []);
}
// console.log(result);
} while (n.length > 0);
return result;
}
const r0 = cleanOpposites(arr);
console.log(arr);
console.log(r0);
The cleaning process should be recursive due to this:
In the first iteraction we get this result:
indexes of items deleted: [1, 2, 5, 6]
resulting array: ["N", "S", "W", "W"]
But there remains ["N", "S",... that shouldn't be part of the final result, so to achieve your requirement, I think we must iterate through the checkForOpposites function till it returns no matches.
Certainly, the code can be shortened, but this would give you an idea of how to do it.
I am writing code for my one of the exercises in freecodecamp.com called as Pig Latin problem. For a while loop it should stop executing the code inside it when the condition becomes wrong.For my case the while loop must stop executing the codes inside it when it finds that it seen a vowel in the charas array during iteration. I think my code is correct in my point of view, but while loop is not stopping execution when it sees a vowel instead it iterate through every element in the charas array.
Here is my code
function translatePigLatin(str) {
var vowels = ['a','e','i','o','u'];
var f="";
var charas = str.split("");
if(vowels.indexOf(charas[0])!==-1) {
// vowel
charas.push("w");
charas.push("a");
charas.push("y");
f = charas.join("");
} else {
//if first letter is a consonant or cluster of consonants
var i = 0;
while(vowels.indexOf(charas[i]) ===-1) {
charas.push(charas[i]);
charas.splice(i,1);
i = i+1;
}
charas.push('a');
charas.push('y');
f = charas.join("");
}
return f;
}
translatePigLatin("california");
It works as work cause
charas.push(charas[i]);
charas.splice(i,1);
i = i+1;
After the first iteration it move 'a' letter at the begging as result i == 1 (in second iteration) charas[i] refers to consonant 'l'.
Your problem is that you increment i. You move the first element from the start of the array and then increment i you are skipping a letter because what was charas[1] is now charas[0] and what is charas[1] was charas[2].
If you step through the code and inspect the charas array you can see this happening:
Starting state:
["c", "a", "l", "i", "f", "o", "r", "n", "i", "a"]
"c" gets moved to the end
i is incremented to 1
["a", "l", "i", "f", "o", "r", "n", "i", "a", "c"]
"l" is at position 1, so it gets moved to the end.
i is incremented to 2
["a", "i", "f", "o", "r", "n", "i", "a", "c", "l"]
"f" is at position 2, so it gets moved to the end.
i is incremented to 3
["a", "i", "o", "r", "n", "i", "a", "c", "l", "f"]
"r" is at position 3, so it gets moved to the end.
i is incremented to 4
["a", "i", "o", "n", "i", "a", "c", "l", "f", "r"]
"i" is at position 4, the while condition is met, "aioniaclfr" will be returned.
If you just get rid of i and always check charas[0] it works like expected:
function translatePigLatin(str) {
var vowels = ['a','e','i','o','u'];
var f = "";
var charas = str.split("");
if(vowels.indexOf(charas[0]) !== -1) {
// vowel
charas.push("w");
charas.push("a");
charas.push("y");
f = charas.join("");
} else {
//if first letter is a consonant or cluster of consonants
while(vowels.indexOf(charas[0]) === -1) {
charas.push(charas[0]);
charas.splice(0,1);
}
charas.push('a');
charas.push('y');
f = charas.join("");
}
return f;
}
document.getElementById('out').textContent = translatePigLatin("california");
<div id="out"></div>
As a side note, this type of while condition will lead to an infinite loop if someone passes in a string that is all consonants, it will just keep shuffling the letters around because it will never find a vowel to stop it. To avoid this, I would add another if condition to check for that to make sure it won't happen:
function translatePigLatin(str) {
var vowels = ['a','e','i','o','u'];
var f = "";
var charas = str.split("");
if (!str.match(/[aeiou]+/)) {
// only consonants do something
f = str + 'ay';
} else if (vowels.indexOf(charas[0]) !== -1) {
// vowel
charas.push("w");
charas.push("a");
charas.push("y");
f = charas.join("");
} else {
//if first letter is a consonant or cluster of consonants
while(vowels.indexOf(charas[0]) === -1) {
charas.push(charas[0]);
charas.splice(0,1);
}
charas.push('a');
charas.push('y');
f = charas.join("");
}
return f;
}
document.getElementById('out').textContent = translatePigLatin("wkrp");
<div id="out"></div>
/[aeiou]+/ is a regular expression meaning any vowel one or more times anywhere in the string the ! in !str.match(/[aeiou]+/) negates the result of match, so if there are no vowels in the string that branch of the if is followed.
You haven't added the condition to exit the while loop, use i <= length of charas. Check below snippet.
function translatePigLatin(str) {
var vowels = ['a', 'e', 'i', 'o', 'u'];
var f = "";
var charas = str.split("");
if (vowels.indexOf(charas[0]) !== -1) {
// vowel
charas.push("w", "a", "y");
f = charas.join("");
} else {
//if first letter is a consonant or cluster of consonants
var i = 0;
var len = charas.length;
while (vowels.indexOf(charas[i]) === -1 && i <= len) {
charas.push(charas[i]);
charas.splice(i, 1);
i++;
}
charas.push('a', 'y');
f = charas.join("");
}
return f;
}
console.log(translatePigLatin("california"));
The problem is that your are iterating AND modifying the same array at the same time
You can simplify your code like this
function translatePigLatin(str) {
var vowels = ['a', 'e', 'i', 'o', 'u'];
//start with vowel
if (vowels.indexOf(str[0]) !== -1) {
return str + "way";
}
var i = 0;
var beforeVowel = "";
var chars = str.split("");
while (vowels.indexOf(chars[i]) === -1 && i < str.length) {
beforeVowel += chars[i];
i++;
}
return str.substring(i) + beforeVowel + "ay";
}
console.log(translatePigLatin("california"));
console.log(translatePigLatin("pig"));
console.log(translatePigLatin("eat"));
I'm trying to sort a paragraph alphabetically, not according to the normal ABC but a made-up one (var order).
I wrote this function and it works great, but only for the first letter of each word - not in-word sorting as well (for example, in correct ABC 'banana' would come before 'birthday').
I'm not sure where to go from here.
$("#send").click(function () {
var text = $("#text").val().replace(/[^A-Za-z0-9_\s]/g, "").toUpperCase().split(" ");
var order = ["Q", "B", "K", "D", "H", "V", "Z", "E", "F", "O", "G", "L", "M", "S", "N", "P", "I", "X", "A", "R", "W", "U", "C", "J", "T", "Y"];
var i, t, j;
var newText = []; // will hold the new alphabet
// function to sort the words:
for (i = 0; i < order.length; i++) {
for (t = 0; t < text.length; t++) {
var firstChar = text[t][0];
if (order[i] == firstChar) {
newText.push(text[t]);
}
}
}
console.log(newText.join(','));
});
EDIT:
An example input can be: "Hi dan don't you think that this is awesome",
and I want the output to be: "don't dan hi is awesome this think that you".
You could use an object with the index of the letters and use Array#sort with a callback which looks for every letter adn calculates the order.
function foo(text) {
var text = text.replace(/[^A-Za-z0-9_\s]/g, "").toUpperCase().split(" "),
order = "QBKDHVZEFOGLMSNPIXARWUCJTY",
ref = {};
order.split('').forEach(function (a, i) { ref[a] = i + 1; });
text.sort(function (a, b) {
var i = 0, v;
do {
v = (ref[a[i]] || 0) - (ref[b[i]] || 0);
i++;
} while (!v)
return v;
});
console.log(text.join(', '));
}
foo('a aa ab b ba bb');
foo('banana birthday');
The problem with your algorithm is that it only compares the first letter in each word, but if the letters are the same the algorithm needs to compare the next letter in each word. Here's a solution that uses recursion:
function doSort(inputArr) {
var words = inputArr.slice(0);
var alphabet = ["Q", "B", "K", "D", "H", "V", "Z", "E", "F", "O", "G", "L", "M", "S", "N", "P", "I", "X", "A", "R", "W", "U", "C", "J", "T", "Y"];
words.sort(function(item1, item2) {
return sortRecursive(item1, item2, 0);
});
function sortRecursive(item1, item2, idx) {
if (item1.length <= idx && item2.length <= idx) {
return 0;
} else if (item1.length <= idx) {
return -1;
} else if (item2.length <= idx) {
return 1;
} else if (item1[idx] == item2[idx]) {
return sortRecursive(item1, item2, idx+1);
} else {
return alphabet.indexOf(item1[idx].toUpperCase()) - alphabet.indexOf(item2[idx].toUpperCase());
}
}
return words;
}
var arr = ["banana", "quebec", "bird", "birthday", "birdman", "bird"];
var sortedArr = doSort(arr);
console.log('unsorted',arr);
console.log('sorted', sortedArr);
https://jsfiddle.net/2qgaaozo/
I'm using regex to test certain elements in an array of arrays. If an inner array doesn't follow the desired format, I'd like to remove it from the main/outer array. The regex I'm using is working correctly. I am not sure why it isn't removing - can anyone advise or offer any edits to resolve this problem?
for (var i = arr.length-1; i>0; i--) {
var a = /^\w+$/;
var b = /^\w+$/;
var c = /^\w+$/;
var first = a.test(arr[i][0]);
var second = b.test(arr[i][1]);
var third = c.test(arr[i][2]);
if ((!first) || (!second) || (!third)){
arr.splice(i,1);
}
When you cast splice method on an array, its length is updated immediately. Thus, in future iterations, you will probably jump over some of its members.
For example:
var arr = ['a','b','c','d','e','f','g']
for(var i = 0; i < arr.length; i++) {
console.log(i, arr)
if(i%2 === 0) {
arr.splice(i, 1) // remove elements with even index
}
}
console.log(arr)
It will output:
0 ["a", "b", "c", "d", "e", "f", "g"]
1 ["b", "c", "d", "e", "f", "g"]
2 ["b", "c", "d", "e", "f", "g"]
3 ["b", "c", "e", "f", "g"]
4 ["b", "c", "e", "f", "g"]
["b", "c", "e", "f"]
My suggestion is, do not modify the array itself if you still have to iterate through it. Use another variable to save it.
var arr = ['a','b','c','d','e','f','g']
var another = []
for(var i = 0; i < arr.length; i++) {
if(i%2) {
another.push(arr[i]) // store elements with odd index
}
}
console.log(another) // ["b", "d", "f"]
Or you could go with Array.prototype.filter, which is much simpler:
arr.filter(function(el, i) {
return i%2 // store elements with odd index
})
It also outputs:
["b", "d", "f"]
Your code seems to work to me. The code in your post was missing a } to close the for statement but that should have caused the script to fail to parse and not even run at all.
I do agree with Leo that it would probably be cleaner to rewrite it using Array.prototype.filter though.
The code in your question would look something like this as a filter:
arr = arr.filter(function (row) {
return /^\w+$/.test(row[0]) && /^\w+$/.test(row[1]) && /^\w+$/.test(row[2]);
});
jsFiddle
I'm assuming it is 3 different regular expressions in your actual code, if they are all identical in your code you can save a little overhead by defining the RegExp literal once:
arr = arr.filter(function (row) {
var rxIsWord = /^\w+$/;
return rxIsWord.test(row[0]) && rxIsWord.test(row[1]) && rxIsWord.test(row[2]);
});