我如何在。map中跳过数组元素?

我的代码:

var sources = images.map(function (img) {
    if(img.src.split('.').pop() === "json"){ // if extension is .json
        return null; // skip
    }
    else{
        return img.src;
    }
});

这将返回:

["img.png", null, "img.png"]

当前回答

为了推断Felix Kling的评论,你可以像这样使用.filter():

var sources = images.map(function (img) {
  if(img.src.split('.').pop() === "json") { // if extension is .json
    return null; // skip
  } else {
    return img.src;
  }
}).filter(Boolean);

这将从.map()返回的数组中删除错误值。

你可以进一步简化如下:

var sources = images.map(function (img) {
  if(img.src.split('.').pop() !== "json") { // if extension is .json
    return img.src;
  }
}).filter(Boolean);

甚至可以使用箭头函数、对象解构和&&操作符作为一行代码:

var sources = images.map(({ src }) => src.split('.').pop() !== "json" && src).filter(Boolean);

其他回答

这里有一个有趣的解决方案:

/**
 * Filter-map. Like map, but skips undefined values.
 *
 * @param callback
 */
function fmap(callback) {
    return this.reduce((accum, ...args) => {
        const x = callback(...args);
        if(x !== undefined) {
            accum.push(x);
        }
        return accum;
    }, []);
}

与绑定操作符一起使用:

[1,2,-1,3]::fmap(x => x > 0 ? x * 2 : undefined); // [2,4,6]

从2019年开始,Array.prototype.flatMap是一个很好的选择。

images.flatMap(({src}) => src.endsWith('.json') ? [] : src);

中数:

flatMap可以作为一种添加和删除项目的方法(修改 项目数目)在一个地图。换句话说,它允许您进行映射 多项对多项(通过分别处理每个输入项), 而不是总是一对一。在这个意义上,它就像 filter的反义词。只需返回一个1元素的数组来保存该项, 用于添加项的多元素数组,或用于删除项的0元素数组 的项目。

我使用foreach():

var sources = [];

images.forEach(function (img) {
    if(img.src.split('.').pop() !== "json"){ // if extension is .json
        sources.push(img);
    }
});

注:我否定了你的逻辑。

先.filter()它:

var sources = images.filter(function(img) {
  if (img.src.split('.').pop() === "json") {
    return false; // skip
  }
  return true;
}).map(function(img) { return img.src; });

如果你不想这样做,这并不是不合理的,因为它有一些成本,你可以使用更通用的.reduce()。你通常可以用.reduce来表示.map():

someArray.map(function(element) {
  return transform(element);
});

可以写成

someArray.reduce(function(result, element) {
  result.push(transform(element));
  return result;
}, []);

因此,如果你需要跳过元素,你可以使用.reduce()轻松完成:

var sources = images.reduce(function(result, img) {
  if (img.src.split('.').pop() !== "json") {
    result.push(img.src);
  }
  return result;
}, []);

在该版本中,来自第一个示例的.filter()中的代码是.reduce()回调的一部分。只有在过滤操作保留结果数组的情况下,才会将图像源推入结果数组。

更新-这个问题得到了很多关注,我想补充以下澄清意见。作为一个概念,.map()的目的正是“map”的意思:根据某些规则将一个值列表转换为另一个值列表。就像某些国家的纸质地图如果完全缺少几个城市就会显得很奇怪一样,从一个列表映射到另一个列表只有在有1对1的结果值集时才有意义。

我并不是说,从一个旧列表中创建一个新列表并排除一些值是没有意义的。我只是试图说明.map()只有一个简单的意图,即创建一个与旧数组长度相同的新数组,只是使用由旧值转换形成的值。

你可以使用map()方法的after。例如在你的例子中,filter()方法:

var sources = images.map(function (img) {
  if(img.src.split('.').pop() === "json"){ // if extension is .json
    return null; // skip
  }
  else {
    return img.src;
  }
});

过滤方法:

const sourceFiltered = sources.filter(item => item)

然后,只有现有的项在新数组sourceFiltered中。