如何在.map()中跳过一个元素?

856

如何在.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"]

51
无法做到,但可以在操作之后过滤掉所有的空值。 - Felix Kling
1
为什么不呢?我知道使用continue不起作用,但是了解原因会很好(也可以避免双重循环)-编辑-对于您的情况,您是否可以反转if条件并仅在split pop的结果!= json时返回img.src - GrayedFox
1
@GrayedFox,那么隐式的 undefined 将被放入数组中,而不是 null。并没有更好... - FZs
@GrayedFox对于初始数组中的每个元素,map函数将插入子函数的返回值,因此无法避免返回一个值。要避免双重循环,请使用for循环或forEach来填充一个新数组。 - undefined
19个回答

4

const arr = [0, 1, '', undefined, false, 2, undefined, null, , 3, NaN];
const filtered = arr.filter(Boolean);
console.log(filtered);

/*
    Output: [ 1, 2, 3 ]
*/


3

如何在 ES5/ES6 中一行代码判断变量是否为 null 或 undefined

//will return array of src 
images.filter(p=>!p.src).map(p=>p.src);//p = property


//in your condition
images.filter(p=>p.src.split('.').pop() !== "json").map(p=>p.src);

1

在你的方法map()之后,你可以使用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:

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

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

1

我使用.forEach来遍历数组,并将结果推入results数组中,然后使用它。通过这种解决方案,我不会两次循环遍历数组。


0
你可以像这样使用 map + 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(x => x !== null);

0

我使用 foreach()

var sources = [];

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

注意:我否定了你的逻辑。


0

你可以做到这个

var sources = [];
images.map(function (img) {
    if(img.src.split('.').pop() !== "json"){ // if extension is not .json
        sources.push(img.src); // just push valid value
    }
});


2
这不适用于 map。相反,您可以像所选答案中那样使用 forEachreduce - nrofis
Array.map() 的重点在于它返回结果。因此,上面的建议不太易读。 - OlleMattsson
在Perl中,可以像这样做一些简单的事情:[ "first", "a" eq "ab" ? "second" : () ]。到目前为止,我还没有找到JavaScript中像那样简单的东西。 - Tim Potapov

0

这是由@theprtk提供的代码更新版本。为了展示一般化版本并提供一个例子,它已经进行了一些清理。

注意:我想在他的帖子下留言,但我还没有足够的声望。

/**
 * @see http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
 * @description functions that transform reducing functions
 */
const transduce = {
  /** a generic map() that can take a reducing() & return another reducing() */
  map: changeInput => reducing => (acc, input) =>
    reducing(acc, changeInput(input)),
  /** a generic filter() that can take a reducing() & return */
  filter: predicate => reducing => (acc, input) =>
    predicate(input) ? reducing(acc, input) : acc,
  /**
   * a composing() that can take an infinite # transducers to operate on
   *  reducing functions to compose a computed accumulator without ever creating
   *  that intermediate array
   */
  compose: (...args) => x => {
    const fns = args;
    var i = fns.length;
    while (i--) x = fns[i].call(this, x);
    return x;
  },
};

const example = {
  data: [{ src: 'file.html' }, { src: 'file.txt' }, { src: 'file.json' }],
  /** note: `[1,2,3].reduce(concat, [])` -> `[1,2,3]` */
  concat: (acc, input) => acc.concat([input]),
  getSrc: x => x.src,
  filterJson: x => x.src.split('.').pop() !== 'json',
};

/** step 1: create a reducing() that can be passed into `reduce` */
const reduceFn = example.concat;
/** step 2: transforming your reducing function by mapping */
const mapFn = transduce.map(example.getSrc);
/** step 3: create your filter() that operates on an input */
const filterFn = transduce.filter(example.filterJson);
/** step 4: aggregate your transformations */
const composeFn = transduce.compose(
  filterFn,
  mapFn,
  transduce.map(x => x.toUpperCase() + '!'), // new mapping()
);

/**
 * Expected example output
 *  Note: each is wrapped in `example.data.reduce(x, [])`
 *  1: ['file.html', 'file.txt', 'file.json']
 *  2:  ['file.html', 'file.txt']
 *  3: ['FILE.HTML!', 'FILE.TXT!']
 */
const exampleFns = {
  transducers: [
    mapFn(reduceFn),
    filterFn(mapFn(reduceFn)),
    composeFn(reduceFn),
  ],
  raw: [
    (acc, x) => acc.concat([x.src]),
    (acc, x) => acc.concat(x.src.split('.').pop() !== 'json' ? [x.src] : []),
    (acc, x) => acc.concat(x.src.split('.').pop() !== 'json' ? [x.src.toUpperCase() + '!'] : []),
  ],
};
const execExample = (currentValue, index) =>
  console.log('Example ' + index, example.data.reduce(currentValue, []));

exampleFns.raw.forEach(execExample);
exampleFns.transducers.forEach(execExample);

-3

.map() 之后使用 .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(x => x);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接