有没有一种方法可以根据其长度删除代码中的特定元素?

时间:2020-07-14 16:05:18

标签: javascript arrays

我在这里有这段代码,该代码应考虑这些不同项的长度,如果长度大于4,则应删除这些值。但是,它说if(array [i] .length> 4)未定义

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));

2 个答案:

答案 0 :(得分:3)

您可以使用Array.filter()

let words = ["Apple", "Ben", "Ice", "Dog", "Tornado"].filter(w => w.length <= 4);


console.log(words);

答案 1 :(得分:2)

恐怕这段代码有很多问题。已经提供了简单的答案:使用filter。如果您仅想知道这些,那就太好了。如果您想通过此方法获得可用的版本,请执行以下步骤:

我们从

开始
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));

首先要注意的是,我们在调用console.log的结果上调用removeWords。但是removeWords不返回任何内容。因此,让我们首先解决该问题:

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  
}

但是现在让我们看看您正在执行的测试。 if (array.length > 4)。您想测试循环内的 ,因为您想测试列表中的每个单词。您已经有了循环,但是它仅包含console.log语句的调试代码。让我们将其移出并在其中移入测试及其相关更改:

function removeWords(array) {
  for (var i = 0; i < array.length; i++) {
    if (array.length > 4) {  //  ---\
      array[i].splice();     //  --- >---- moved inside loop
    }                        //  ---/
  }
  return array;
}

但是现在让我们看一下实际测试。我们应该检查 word 的长度是否大于4,而不是 array 的长度。因此,我们需要检查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;
}

splice调用中,我们遇到了相反的问题。当您想在数组上执行此操作时,尝试在单词上调用splice。您要删除数组中第i个索引处的一个元素。我们可以通过

解决该问题
function removeWords(array) {
  for (var i = 0; i < array.length; i++) {
    if (array[i].length > 4) {
      array.splice(i, 1);  // <----------- changed
    }
  }
  return array;
}

下一个问题更加微妙。而且它甚至不会影响您的测试用例。但是,如果我们针对以下列表运行此函数:["Apple", "Ben", "Ice", "Dog", "Tornado", "Windshield", "Axe"],我们将返回["Ben", "Ice", "Dog", "Windshield", "Axe"]。由于您的循环和"Windshield"调用之间存在交互,因此我们在此处包含splice。我们会继续努力,直到将i设置为3。此时,我们的数组包括["Ben", "Ice", "Dog", "Tornado", "Windshield", "Axe"],因为我们已经删除了“ Apple”。我们检查索引3,发现“龙卷风”有四个以上的字母,再次splice,剩下["Ben", "Ice", "Dog", "Windshield", "Axe"]。但是现在索引是4,测试词是"Axe",我们已经跳过了“ Windshield”!

之所以会这样,是因为,当您要测试数组中的每个单词时,您的splice调用会随着您的更改数组的长度。解决此问题的一种方法是反向循环。从头开始,splice仅会影响您已经测试过的事物的索引。可能看起来像这样:

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;
}

这是代码的第一个工作版本。我们可以把它留在那里。但是仍然存在潜在的问题。您可以随时更改输入。有很强的思想流派发现这是一件非常可怕的事情。因此,让我们先对其进行复制,然后再进行更改并返回,而不是更改原始输入数据。我们可以采用多种方法对输入进行浅表克隆,包括使用sliceconcat。现代的大概是这样使用传播符号:

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;
}

这是该函数的一个合理版本...如果我们还没有Array.prototype.filter可用的话。您可以在以下代码段中看到它的运行情况:

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}