An Alternative to filter().map(): Using flatMap()
Raja Jaganathan

Raja Jaganathan @rajajaganathan

About: JavaScript/TypeScript, React.js, Node.js developer

Location:
Chennai, India
Joined:
May 12, 2017

An Alternative to filter().map(): Using flatMap()

Publish Date: Feb 22
18 14

When working with arrays, developers often use Array.filter().map() to transform data. But did you know Array.flatMap() can achieve the same result in a single step? Let’s explore when to use each.

Old Approach with 2 iteration: filter().map()

const persons = [
  { name: "Raja", age: 36 },
  { name: "Jaganathan", age: 65 },
  { name: "Kumar", age: 50 }
];

const result = persons.filter(p => p.age > 60).map(p => p.name);
console.log(result); // ["Jaganathan"]
Enter fullscreen mode Exit fullscreen mode

Here, .filter() first selects the matching objects, and then .map() extracts names. Though it involves two loops, modern JavaScript engines optimize it well, making it faster in many cases.

New Approach with 1 iteration: flatMap()

const result = persons.flatMap(({ age, name }) => age > 60 ? name : []);
console.log(result); // ["Jaganathan"]
Enter fullscreen mode Exit fullscreen mode

With flatMap(), we combine filtering and mapping in one pass, making the code more concise. However, performance may slightly drop because flatMap() internally flattens arrays, adding overhead.

Performance Comparison

Multiple approaches have been tested on jsperf.app. Thanks @miketalbot and @webjose.

🔹 flatMap() vs filter().map() – There’s no clear winner, but flatMap() shows a slight performance advantage in some cases.

When to Use Each

✅ Use filter().map() when clarity and semantic intent are important.
✅ Use flatMap() when reducing iterations and simplifying code structure matters more than micro-optimizations.

Happy Coding! 😊

Comments 14 total

  • Sathyamoorthi P
    Sathyamoorthi PFeb 22, 2025

    Good one Raja. Thx for introducing a new method with detailed performance reasoning.

  • Mike Talbot ⭐
    Mike Talbot ⭐Feb 22, 2025

    Is it more readable though? I'm not sure about that.

    Anyway, flatMap can be made to perform faster than .filter then .map if you are more careful with the array construction:

    • You don't need to wrap name in an array
    • You can use a single predefined dummy array in the empty result
    const filter_out = []
    
    persons.flatMap(({ age, name }) => age > 60 ? name : filter_out);
    
    Enter fullscreen mode Exit fullscreen mode

    Doing this improves the performance, so it becomes the fastest method. However, flatMap does not tell me you are doing a filter and a map; it tells me you are dealing with arrays of arrays, so I find the intent of the code requires significant parsing, which is probably not worth the 5% speed improvement.

    Performance results: jsperf.app/baxase

    • Raja Jaganathan
      Raja JaganathanFeb 22, 2025

      Agreed flatMap has different purpose and semantic too. just illustrate for different use case.I miss the point of the unwanted array creation.

    • José Pablo Ramírez Vargas
      José Pablo Ramírez VargasFeb 22, 2025

      As always, Mike making sense. Thanks for the insightful post.

      I made an edition to your performance test because I think we should never lose sight of what plain JS can do: Version 2 of performance tests

      As expected, plain JS beats them all.

    • José Pablo Ramírez Vargas
      José Pablo Ramírez VargasFeb 22, 2025

      Even more tests: Version 3

      This one demonstrates that the encapsulation of code is rather costly. If this were C++ or a similar language, this would be an indication that the function needs to be inlined.

      Anyway, this was fun. Thanks, Mike! I learned about this performance website because of your insightful comment.

      • Mike Talbot ⭐
        Mike Talbot ⭐Feb 22, 2025

        Wow, yeah, that's the thing isn't it - 2x the speed if we just use a normal loop... That shocked me, so I tried it with an iterator loop rather than a for...of, and there's a new winner (for which I'm slightly shocked)!!!

        Version 4

        • Mike Talbot ⭐
          Mike Talbot ⭐Feb 22, 2025

          Also, damn good point about the encapsulation, that is odd...

          • José Pablo Ramírez Vargas
            José Pablo Ramírez VargasFeb 22, 2025

            Ok, this is fun.

            Version 5

            I have encapsulated the code in a reusable function as before, only with the winner that iterates over the index of the array.

            Look at the differences. Here's a screenshot ran in MS Edge v133:

            Image description

            Label #1 is the fastest one, your proposal using the iterator, then there's #2 which is the original encapsulated one. 45% slower. Damn!! But #3 is the iterator version encapsulated and is only 5 or 8% slower. This tells me that there's something wrong in Chromium. It doesn't have much sense to me such big difference. But what do I know.

            Anyway, notice how there might be a difference between using ++i and i++. In C/C++, overloading this operator tellls you something very interesting: ++i is more performant (in C++) because i++ has to create a copy of itself to be used as return value. It might be true for JavaScript too.

            • Mike Talbot ⭐
              Mike Talbot ⭐Feb 23, 2025

              Wow, that is fascinating... You're right, some very unexpected behaviour that...

    • Sathyamoorthi P
      Sathyamoorthi PFeb 25, 2025

      This will be much simpler for readability

      const filter = [];
      persons.flatMap(obj => (obj.age > 60) ? obj.name : filter);
      
      Enter fullscreen mode Exit fullscreen mode
  • leob
    leobFeb 24, 2025

    More readable? Not at all, IMO ...

    Chaining steps is the essence of this approach, and "filter" followed by "map" expresses that approach and that thought process much more clearly ...

  • npm i elijahmanor
    npm i elijahmanorFeb 24, 2025

    Nice post. Another alternative would be reduce, however it is questionable on how readable it is in comparison :)

    jsperf.app/baxase/6

  • Buecui Salos
    Buecui SalosFeb 26, 2025

    Array.flatMap() is a great alternative to filter().map() for simplifying code by combining filtering and mapping into one iteration. While filter().map() is clear and easy to understand, flatMap() can be more concise and reduce iterations. However, flatMap() can introduce slight performance overhead due to internal array flattening. Use filter().map() when clarity matters and flatMap() for optimizing iterations.

    Also, for those in Riyadh, remember to check the Salah times!

  • Areeba Nishat
    Areeba NishatMay 16, 2025

    The flatMap() method first maps each element using a mapping function, then flattens the result into a new array. It combines the functionality of map() followed by flat().
    GeeksforGeeks

    Example:

    javascript
    Copy
    Edit
    const arr = [1, 2, 3, 4, 5];
    const result = arr.flatMap(x => x % 2 === 0 ? [x * 2] : []);
    console.log(result); // Output: [4, 8]
    In this example, flatMap() filters out odd numbers and doubles the even numbers in one step.

    ✅ Advantages of flatMap() over filter().map()
    Conciseness: Reduces the need for multiple method calls, leading to cleaner and more readable code.

    Performance: In some cases, flatMap() can be more efficient than chaining filter() and map(), as it performs both operations in a single pass over the array.

    Type Safety: In TypeScript, flatMap() can provide more accurate type inference, especially when dealing with nullable or optional values.
    Peerigon GmbH

    ⚠️ Considerations
    Flattening Depth: flatMap() only flattens the array to a depth of 1. If your mapping function returns nested arrays with more than one level, you may need to use flatMap() in combination with flat().
    GeeksforGeeks

    Compatibility: Ensure that your environment supports flatMap(), as it may not be available in older JavaScript versions.

    In summary, flatMap() is a powerful method that can simplify your code and improve performance when you need to filter and transform elements in one step.

Add comment