163

I'm trying to use ES6 arrow function with .filter to return adults (Jack & Jill). It appears I cannot use an if statement.

What do I need to know in order to do this in ES6?

var family = [{"name":"Jack",  "age": 26},
              {"name":"Jill",  "age": 22},
              {"name":"James", "age": 5 },
              {"name":"Jenny", "age": 2 }];

let adults = family.filter(person => if (person.age > 18) person); // throws error

(8:37) SyntaxError: unknown: Unexpected token (8:37)
|let adults = family.filter(person => if (person.age > 18) person);

My working ES5 example:

let adults2 = family.filter(function (person) {
  if (person.age > 18) { return person; }
});
hzhu
  • 3,759
  • 5
  • 29
  • 39
  • (8:37) SyntaxError: unknown: Unexpected token (8:37) |let adults = family.filter(person => if (person.age > 18) people); – hzhu Aug 16 '15 at 22:08

6 Answers6

260

It appears I cannot use an if statement.

Arrow functions either allow to use an expression or a block as their body. Passing an expression

foo => bar

is equivalent to the following block

foo => { return bar; }

However,

if (person.age > 18) person

is not an expression, if is a statement. Hence you would have to use a block, if you wanted to use if in an arrow function:

foo => {  if (person.age > 18) return person; }

While that technically solves the problem, this a confusing use of .filter, because it suggests that you have to return the value that should be contained in the output array. However, the callback passed to .filter should return a Boolean, i.e. true or false, indicating whether the element should be included in the new array or not.

So all you need is

family.filter(person => person.age > 18);

In ES5:

family.filter(function (person) {
  return person.age > 18;
});
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Ah, what a great explanation. In .filter() if nothing is returned for an object, it's assumed as false? For example, in your ES5 example, only the true elements are returned. – hzhu Aug 16 '15 at 22:58
  • 2
    @HenryZhu: Yes. But my example always returns either `false` or `true`, since `person.age > 18` is always either `false` or `true`. – Felix Kling Aug 16 '15 at 23:08
  • The version with the "un-blocked" if was supposed to return `person` (of course it doesn't do that as you pointed...). Had your first correction actually done that (`foo => { if (person.age > 18) return person }`), you'd get the exact equivalent of what OP used in the ES5 code. While that's a confusing code, it DOES work, and WILL solve the problem. `return person` will coerce to `true`, and no return will "return" `undefined`, which will be coerced to `false`. – Amit Aug 17 '15 at 14:24
  • 1
    @Amit: Sure. I thought because the other answer suggested it, I wouldn't have to. However, this may be confusing, so I updated it. – Felix Kling Aug 17 '15 at 15:10
  • Also there is a nice place to ternary expression `person.age > 18 ? 'a': 'b'` – just-boris Aug 17 '15 at 21:16
  • 2
    @just-boris: Not sure what this would achieve here with `.filter`. Do you mean arrow functions in general? – Felix Kling Aug 17 '15 at 21:17
  • @FelixKling, yes in, general. It also works well in `map`, `reduce` and other places for arrow function. Here comparison is enough – just-boris Aug 18 '15 at 12:04
  • filter() is actually ES5 not ES6 – Carlos Mafla Sep 12 '18 at 10:03
  • @CarlosMafla: did anyone claim it was ES6? – Felix Kling Sep 12 '18 at 10:09
  • @FelixKling sorry, I don't even remember why I made that comment, I probably misread something. – Carlos Mafla Sep 14 '18 at 14:23
55

You can't implicitly return with an if, you would need the braces:

let adults = family.filter(person => { if (person.age > 18) return person} );

It can be simplified though:

let adults = family.filter(person => person.age > 18);
Kit Sunde
  • 35,972
  • 25
  • 125
  • 179
  • Awesome, the second one works. The first one returns an empty array. Any ideas? – hzhu Aug 16 '15 at 22:12
  • 1
    @HenryZhu: It works just fine (probably something else is wrong with your code or transpiler). But that's not the right way anyway. – Felix Kling Aug 16 '15 at 22:22
  • 1
    How would this be done in the case that you have an else statement? I am trying to see this with a ternary but cannot seem to identify the correct syntax – Winnemucca Jan 12 '17 at 16:45
  • @stevek Exactly like you would with a normal function like in the first example. – Kit Sunde Jan 12 '17 at 16:48
5
return arrayname.filter((rec) => rec.age > 18)

Write this in the method and call it

shreyasm-dev
  • 2,711
  • 5
  • 16
  • 34
javadev
  • 71
  • 1
  • 5
3

As simple as you can use const adults = family.filter(({ age }) => age > 18 );

const family =[{"name":"Jack",  "age": 26},
              {"name":"Jill",  "age": 22},
              {"name":"James", "age": 5 },
              {"name":"Jenny", "age": 2 }];

const adults = family.filter(({ age }) => age > 18 );

console.log(adults)
Mo.
  • 26,306
  • 36
  • 159
  • 225
2

Here is my solution for those who use hook; If you are listing items in your grid and want to remove the selected item, you can use this solution.

var list = data.filter(form => form.id !== selectedRowDataId);
setData(list);
Sabri Meviş
  • 2,231
  • 1
  • 32
  • 38
0

Another good option is use the ternary operator like as filter in the map and use the filter for take off the nulls value

var family = [{"name":"Jack",  "age": 26},
              {"name":"Jill",  "age": 22},
              {"name":"James", "age": 5 },
              {"name":"Jenny", "age": 0 }];
              
let adults = family.map(person => person.age < 18?person:null).filter(Boolean);

// or if you are afraid about filter(Boolean) you could use filter(person => person != null);

adults.forEach(element => console.log(element))