JavaScript迭代算法接受数组中应该拒绝的一半分数



我想检查我的变量是否是一个数组,以及它的元素是否包含带有".png"或".jpg"的子字符串。所以我写了这段代码:

let test = ['empty_250x380@3x.png',
'empty_250x380@3x.png',
'empty_250x380@3x.png',
'empty_250x380@3x.png',
'empty_250x380@3x.png','empty_250x380@3x.png']
if(Array.isArray(test))
{
   for(let n in test)
   {
     if(test[n].includes('.png') || test[n].includes('.PNG') || test[n].includes('.jpg') || test[n].includes('.JPG') )
     {
        test.splice(n,1);
     }
   } 
     console.log(test.length); // here is 3
  };

但它总是让数组的每个偶数索引通过,所以我弄错了一半的分数。我不知道这怎么可能。你知道我该怎么解决吗?

迭代的问题在于索引在splice数组时从0 to 5开始。当索引达到第 3 个元素时,数组的大小变得3,因此没有定义test[3]test[4]test[5]。这就是为什么你要得到 尺寸 3 .尝试从5迭代到0,例如:

let test = ['empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png', 'empty_250x380@3x.png'];
if(Array.isArray(test)) {
  for(let n = test.length - 1; n >= 0; n--) {
    if(test[n].includes('.png') || test[n].includes('.PNG') || test[n].includes('.jpg') || test[n].includes('.JPG')) {
      test.splice(n, 1);
    }
  } 
  console.log(test.length);
};

或者,您可以使用正则表达式来减少代码:

let test = ['empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png', 'empty_250x380@3x.png'];
if(Array.isArray(test)) {
  for(let n = test.length - 1; n >= 0; n--) {
    if(/.(png|jpg)$/i.test(test[n])) {
      test.splice(n, 1);
    }
  } 
  console.log(test.length);
};

更好的版本:

let test = ['empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png', 'empty_250x380@3x.png'];
if(Array.isArray(test)) {
  console.log(test.filter(e => ! /.(png|jpg|svg)$/i.test(e)).length);
};

你可以做什么 检查是否Array.isArray,然后确保arrayevery元素以 .png 或 .jpg

let test = ['empty_250x380@3x.png',
'empty_250x380@3x.png',
'empty_250x380@3x.png',
'empty_250x380@3x.jpg',
'empty_250x380@3x.png','empty_250x380@3x.png']
function check(arr) {
   return Array.isArray(arr) && arr.every(i=>['.jpg','.png'].indexOf(i.slice(-4))!== - 1)
}
console.log(check(test))

使用一些不错的 Array 方法可能会取得更大的成功。为此,您将使用过滤器删除不需要的项目。这样做的好处是不可变的,因此它返回一个新数组,只包含您想要的项目。在我看来,它看起来也好多了。

const acceptableItems = test.filter(filename => {
    // keep the item in the array if it includes png
    return filename.includes('png') ... 
    // OR. remove it from the new array if it includes png
    return !filename.includes('png')
})

该方法正在修改当前数组,从而导致有关当前索引的错误。

另一种方法是执行反向循环,因为主要问题是访问的索引:

let test = ['empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png', 'empty_250x380@3x.png'];
if (Array.isArray(test)) {
  var n = test.length;
  while (n--) {
    if (test[n].includes('.png') || test[n].includes('.PNG') || test[n].includes('.jpg') || test[n].includes('.JPG')) {
      test.splice(n, 1);
      console.log(test);
    }
  }
  console.log(test.length); // here is 3
};

建议:获取每个图像的扩展并使用函数Array.prototype.includes

let test = ['empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png',  'empty_250x380@3x.png', 'empty_250x380@3x.png'],
    allowedExts = ['.png', '.jpg'];
if (Array.isArray(test)) {
  var n = test.length;
  while (n--) {
    var ext = test[n].substring(test[n].lastIndexOf('.')).toLowerCase();
    if (allowedExts.includes(ext)) test.splice(n, 1);
  }
  console.log(test.length);
};

这似乎是一个简单的正则表达式和every()的一个很好的用例。正则表达式允许测试锚定到行尾,因此它不应该匹配像"empty.pngstuff.txt"这样的情况,includes()会匹配这种情况。而且可读性很强。

let test_array = ['empty_250x380@3x.png',
'empty_250x380@3x.png',
'empty_250x380@3x.PNG',
'empty_250x380@3x.jpeg',
'pngempty_250x380@3x.png','empty_250x380@3x.png'
]
// i modifier makes it case insensitive
let re =  RegExp(/.(png|jpeg)$/i)
let result = Array.isArray(test_array) 
             && test_array.every(i => re.test(i))
console.log(result)

最新更新