There are a number of things wrong with this code, I'm afraid. The simple answer has already been supplied: use filter
. If that's all you want to know, great. If you want to work through this to get a working version, here are some steps:
We start with
let words = ["Apple", "Ben", "Ice", "Dog", "Tornado"];
function removeWords(array) {
for (var i = 0; i < array.length; i++) {
console.log(array[i].length);
}
if (array.length > 4) {
array[i].splice();
}
}
console.log(removeWords(words));
The very first thing to notice is that we call console.log
on the result of calling removeWords
. But removeWords
doesn't return anything. So let's fix that first:
function removeWords(array) {
for (var i = 0; i < array.length; i++) {
console.log(array[i].length);
}
if (array.length > 4) {
array[i].splice();
}
return array; // <--------------------- added
}
But now let's look at the test you're doing. if (array.length > 4)
. You want to be testing inside your loop, as you want to test every word in the list. You already have the loop, but it only contains the debugging code of a console.log
statement. Let's move that out and move the test and its related change inside it:
function removeWords(array) {
for (var i = 0; i < array.length; i++) {
if (array.length > 4) { // ---\
array[i].splice(); // --- >---- moved inside loop
} // ---/
}
return array;
}
But now let's look at that actual test. We should be checking that the word has a length greater than 4, not that the array does. So we need to check if array[i] > 4
:
function removeWords(array) {
for (var i = 0; i < array.length; i++) {
if (array[i].length > 4) { // <------ changed
array[i].splice();
}
}
return array;
}
We have the opposite problem in the splice
call. You are trying to call splice
on the word, when you want to do it on the array. You want to remove one element at the i
th index in the array. We can fix that with
function removeWords(array) {
for (var i = 0; i < array.length; i++) {
if (array[i].length > 4) {
array.splice(i, 1); // <----------- changed
}
}
return array;
}
The next problem is more subtle. And it won't even affect your test case. But if we run this function against this list: ["Apple", "Ben", "Ice", "Dog", "Tornado", "Windshield", "Axe"]
, we will get back ["Ben", "Ice", "Dog", "Windshield", "Axe"]
. We include "Windshield"
here because of the interaction between your loop and the splice
call. We proceed merrily along until i
is set to 3
. At this point our array includes ["Ben", "Ice", "Dog", "Tornado", "Windshield", "Axe"]
because we've already removed "Apple". We check index 3, see that "Tornado" has more than four letters, and splice
again, leaving ["Ben", "Ice", "Dog", "Windshield", "Axe"]
. But now the index is 4, and our test word is "Axe"
We've skipped over "Windshield"!
This happens because, while you want to test every word in the array, your splice
call is changing the length of the array as you go. One way to fix this is to loop in reverse. By starting from the end, the splice
will affect the indices only of things you have already tested. That might look like this:
function removeWords(array) {
// +--------------+-----+- changed
// | | |
// v v v
for (var i = array.length - 1; i >= 0; i--) {
if (array[i].length > 4) {
array.splice(i, 1);
}
}
return array;
}
This is the first working version of the code. We could leave it there. But there is still a potential issue. You're changing the input as you go. There is a strong school of thought that finds this to be a pretty terrible thing to do. So instead of changing our original input data, let's make a copy of it first, then change and return this. There are many ways we could make a shallow clone of the input, including using slice
or concat
. The modern one is probably to use the spread notation like this:
function removeWords(words) {
// ^--------+---------- changed
let array = [...words] // <---'
for (var i = array.length - 1; i >= 0; i--) {
if (array[i].length > 4) {
array.splice(i, 1);
}
}
return array;
}
This is now a reasonable version of the function ... if we didn't already have Array.prototype.filter
available. You can see it in action in the following snippet:
function removeWords(words) {
let array = [...words]
for (var i = array.length - 1; i >= 0; i--) {
if (array[i].length > 4) {
array.splice(i, 1);
}
}
return array;
}
let words = ["Apple", "Ben", "Ice", "Dog", "Tornado"];
let words2 = ["Apple", "Ben", "Ice", "Dog", "Tornado", "Windshield", "Axe"];
console.log (removeWords(words));
console.log (removeWords(words2));
console.log ("--------------\nOriginals Untouched\n--------------")
console.log (words);
console.log (words2);
.as-console-wrapper {min-height: 100% !important; top: 0}