Related
What's wrong with my code? It should return true for this array. The invalid one should return false.
Please explain it to me because i'm just started with JS
//arrays :
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const validateCred = Array => {
let cardNum = 0
let reverseArray = Array.reverse()
for (let i = 0; i < reverseArray.length; i++){
let newVar = reverseArray[i]
if (i%2 !== 0){
newVar = reverseArray[i] * 2
if (newVar > 9){
newVar = newVar[i] - 9;
cardNum += newVar
} else {
cardNum += newVar
}
} else {
cardNum += reverseArray[i]
}
}
return(cardNum%10 === 0 ? true : false)
}
console.log(validateCred(valid1))
As you figured out and noted in the comments, this is not going to go well when newVar is a number:
newVar = newVar[i] - 9;
And as Pointy, um, pointed out, Array is a terrible name for a variable, shadowing an important constructor function. More than that, there is a strong convention in JS that InitialCapital variable names are reserved for constructor functions. I would suggest a name that describes what it's for, not its type. Perhaps "creditCard" would be useful, or, depending on your tolerance for short abbreviations, "cc".
But there's another, more subtle, problem with this code. It alters its input:
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
console .log (validateCred (valid1)) //=> true
console .log (valid1) //=> [8, 0, 8, 6, 1, 0, 8, 0, 9, 7, 7, 6, 9, 3, 5, 4]
In a real application, this could cause you all sorts of problems, and maybe far away from this section, always frustrating.
It's easy enough to fix. Just clone the array before reversing it. There are many ways to do it (using myVariable.slice() or myVariable.concat(), for instance.) My preference these days is to spread it into a new array: [...myVariable].
In my answer to another Luhn's Algorithm question, I developed what I think of as an elegant version of this algorithm. If you're new to JS, this may use some features you're not familiar with, but I find it clear and useful. This is a slightly improved version:
const luhn = (ds) => ([...ds]
.filter(d => /^\d$/ .test (d))
.reverse ()
.map (Number)
.map ((d, i) => i % 2 == 1 ? (2 * d > 9 ? 2 * d - 9 : 2 * d) : d)
.reduce ((a, b) => a + b, 0)
) % 10 == 0
It's the same algorithm, just expressed a little more concisely. Between the spreading of the initial value and the filter call (removing non-digits), it allows us to pass various input formats:
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = "4539677908016808"
const valid3 = "4539-6779-0801-6808"
const valid4 = "4539 6779 0801 6808"
i know this is an annoying question, but can someone explain me why splice method is executing in a weird way. Please explain me why the expected output is different from the actual result.
let numbers = [15, 12, 15, 3, 5, 4, 6];
// Get the indexes of the numbers greater than 5
let indexes = numbers.reduce((arr, current, index) => {
if (current > 5) {
arr.push(index);
}
return arr;
}, []);
// Loop through the indexes while removing the indexes from the numbers array
indexes.forEach((element) => {
numbers.splice(element, 1);
});
// expected result: numbers = [ 3 , 5, 4 ];
// actual result: numbers = [ 12, 3, 4, 6 ]
.splice() changes the array it is used on. You might have already known this, but if you debug your code using a console.log, you'll see what's happening; in short, your first number > 5 is 15. 15 is at index 0, so you remove index 0. However, as splice changes the array it is used on, 12 becomes index 0, and then the second 15 index 1, and so on and so forth. So for example, your code has the following indexes: 0, 1, 2, 6.
The first time you remove index 0: [12, 15, 3, 5, 4, 6]
Then you remove index 1: [12, 3, 5, 4, 6]
Then you remove index 2: [12, 3, 4, 6]
Then you remove index 6, which doesn't exist: [12, 3, 4, 6]
The better way of accomplishing that goal is with .filter(). Filter creates a new array of all items that pass the test given in the callback, so:
numbers = numbers.filter((num) => num < 6);
That's the arrow function expression shorthand to return only numbers less than 6.
splice actually removes the item in place. It does not create any copy of array. In your case after reduce operation, indexes would be
[0, 1, 2, 6]
and then while iterating and splicing, in first iteration array with position 0 is removed so array becomes
numbers = [12, 15, 3, 5, 4, 6];
and its length is also reduced. On next iteration of forEach array element with index position 1 is removed which is 15 in our case. So after second iteration array becomes
numbers = [12, 3, 5, 4, 6];
Similarly in next subsequent iteration you will have result like
[12, 3, 4, 6]
As someone has mentioned the problem is with applying changes over an array that is mutated in every iteration.
I assume the example is for learning purposes as it would have been easier to write it like:
let numbers = [15, 12, 15, 3, 5, 4, 6]
numbers.filter(elem => elem <= 5)
In any case, and following the demonstration code, it would be good to stress the dangerous of mutations that is prone to spooky effects. I have rewritten the code in a more functional style:
let numbers = [15, 12, 15, 3, 5, 4, 6];
// Get the indexes of the numbers greater than 5
let indexes = numbers.reduce((arr, current, index) => {
if (current > 5) {
return arr.concat(index);
}
return arr;
}, []);
// Instead of removing we create a new array filtering out the elements we dont want
let filteredNumbers = numbers.filter((_,index) => indexes.indexOf(index) === -1)
console.log(filteredNumbers)
// expected result: numbers = [ 3 , 5, 4 ];
// actual result: numbers = [ 3, 5, 4 ]
let newer = [7,8,10,0,2,3,9,24,1,4,20,19,23,5,21,6,22];
let indices_2= [3,5,0,1,4,6,7,10,**13**,**16**,8,2,9,**14**,**15**,**11**,**12**];
Output should be = [3,5,0,1,4,6,7,10,**21**,**24**,8,2,9,**22**,**23**,**19**,**20**];
Hi guys, this might be tough. If the element in indices_2 is not found in newer, from smallest to largest value, lets say the first smallest number of indices_2 not found in newer is 11, it is replaced by the first smallest number found in newer which is not found in indices_2 which is 19. Then the sequence continues on for the the second smallest number of indices_2 not found in newer.
let newer=[7,8,10,0,2,3,9,24,1,4,20,19,23,5,21,6,22];
let indices_2=[3,5,0,1,4,6,7,10,13,16,8,2,9,14,15,11,12];
let status_indices=[]; let status_indices_stat=[];
for (let i=0;i<newer.length;i++){
status_indices_stat="f"
for (let f=0;f<newer.length;f++){
if (indices_2[i]==newer[f]){
status_indices_stat="t"
//check whether element is found in newer.
}
}
status_indices.push(status_indices_stat)
}
for (let f=0;f<newer.length;f++){
if (status_indices[f]=="f"){
for (let i=0;i<newer.length;i++){
if (indices_2[f]<newer[i]){
console.log(i)
}
}
}
}
You could filter both arrays with the opposite, sort them and take the array with filtered indices as pattern for the index of getting the value of the other filtered and sorted array.
let newer = [7, 8, 10, 0, 2, 3, 9, 24, 1, 4, 20, 19, 23, 5, 21, 6, 22],
indices2 = [3, 5, 0, 1, 4, 6, 7, 10, 13, 16, 8, 2, 9, 14, 15, 11, 12],
temp1 = newer.filter(v => !indices2.includes(v)).sort((a, b) => a - b),
temp2 = indices2.filter(v => !newer.includes(v)).sort((a, b) => a - b),
result = indices2.map(v => newer.includes(v) ? v : temp1[temp2.indexOf(v)]);
console.log(...result);
Here's a sample of the problem I'm having in JavaScript:
first array [1, 2, 3, 4, 5, 6, 7]
second array [7, 8, 9, 4, 2, 5, 7]
In this case, I need to be able to find and eliminate "4" and "7" from both arrays, eliminating both. This is based on their location and matching value.
I haven't been able to find anything other than eliminating matching values. In this case, however, the values must be in the same place and also be matching.
I've tried this so far:
function findCommonElements3(array1, array2) {
return arr1.some(item => arr2.includes(item))
}
it looks like it only looks for matching elements, whereas I need to find matching corresponding elements and then remove them.
As mentioned in the comments, you may use the splice method to remove one or more elements of an array in JavaScript.
First of all I would store the indexes of the elements I should remove looping the array as so:
const array1 = [1, 2, 3, 4, 5, 6, 7];
const array2 = [7, 8, 9, 4, 2, 5, 7];
//Indexes of same elements
var sameIndexes = [];
function findSameIndexes(element, index) {
if (array1[index] == array2[index]) {
sameIndexes.push(index);
}
}
array1.forEach(findSameIndexes);
Calling console.log(sameIndexes) should give this result:
Array [3, 6]
The problem is that if you loop again the array and remove the elements in that order, the indexes would not correspond to the elements anymore.
For example if you remove the 3rd element, the number 7 wouldn't be at index 6 anymore, to solve this issue I'd use the reverse method so you won't lose track of the indexes
// A simple function to remove the elements in both arrays
function removeElements(index) {
array1.splice(index,1);
array2.splice(index,1);
}
sameIndexes.reverse().forEach(removeElements);
And the final results would be
Array [1, 2, 3, 5, 6]
Array [7, 8, 9, 2, 5]
Which hopefully is what you were looking for, of course there are better ways to write it down, but maybe this will help you find a solution.
You could just use a for loop and use index. something like this
const firstarray = [1, 2, 3, 4, 5, 6, 7]
const secondarray = [7, 8, 9, 4, 2, 5, 7]
for (let i = 0; i <= firstarray.length - 1; i++) {
if (firstarray[i] === secondarray[i]) {
console.log(`found ${firstarray[i]} at index ${i}`);
firstarray.splice(i, 1);
secondarray.splice(i, 1);
}
}
console.log(firstarray, secondarray);
const excludeCommon = (ar1, ar2) => {
const both = [...ar1, ...ar2].filter((v, i, ar) => v !== ar[i + (2 * (i < ar1.length) - 1) * ar1.length]);
return [both.slice(0, both.length / 2), both.slice(both.length / 2)];
}
console.log(excludeCommon([1, 2, 3, 4, 5, 6, 7], [7, 8, 9, 4, 2, 5, 7]));
i am trying to splice the odd/evens numbers, look this, i tried to find odd numbers , but on the results array, evens numbers still there ,
function find(index){
for(var i = 0 ; i < index.length;i++) {
for(var j = 0 ; j < index[i].length ; j++) {
if(index[i][j] % 2 === 1) { // trying to find odd numbers
index[i].splice(j, 1)
}
}
}
return index
}
var data = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
var another = [
[2, 2, 7],
[1, 3, 5, 6],
[1, 3, 5, 7, 9, 11]
]
console.log(find(data))
console.log(find(another))
is there any wrong with my codes ?? or i missed something? :)
The problem is that you are mutating the array as you loop over it.
ie. on the second row of your second array, ([1,3,5,6]), lets think about what happens:
i =1, j = 0
the number (1) is odd, so you splice it, the array now looks like [3,5,9]
i = 1, j = 1, the number is 5, is odd, so you remove it. You skipped over 3.
i = 1, j=2, length of the row is 2, so the loop ends.
I've added a console log to your code that demonstrates this.
function find(index){
for(var i = 0 ; i < index.length;i++) {
for(var j = 0 ; j < index[i].length ; j++) {
if (i ===1) console.log(`i = ${i}, j=${j}, index[i] = ${index[i]}, index[i].length=${index[i].length}`);
if(index[i][j] % 2 === 1) { // trying to find odd numbers
index[i].splice(j, 1)
}
}
}
return index
}
var another = [
[2, 2, 7],
[1, 3, 5, 6],
[1, 3, 5, 7, 9, 11]
]
console.log(find(another))
So generally, as a rule, don't loop over arrays and mutate them.
Instead, I recommend using the Array.prototype methods where you can, instead of loops.
A CertainPerformance suggests - you could use filter here instead.
function find(array){
//Assuming array is a 2d array.
return array.map(row => row.filter(v => v%2 ===0));
}
var data = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
var another = [
[2, 2, 7],
[1, 3, 5, 6],
[1, 3, 5, 7, 9, 11]
]
console.log(find(data))
console.log(find(another))
Note that this does return some empty arrays, which maybe you want to keep, or maybe you want to filter again to remove the empty arrays.
Note that, if you're not familiar with it - I'm using the ES6 fat arrow syntax in my answer.