Shouldn't the built-in Array methods be faster than the naive approach for performing such operations? Maybe somebody with more low-level knowledge than I can shed some light on the situation.

I just want to attempt to address this part of the question and more from the conceptual level (with little understanding of the nature of Swift's optimizer on my part) with a "not necessarily". It's coming more from a background in compiler design and computer architecture than deep-rooted knowledge of the nature of Swift's optimizer.

Calling Overhead

With functions like map and reduce accepting functions as inputs, it places a greater strain on the optimizer to put it one way. The natural temptation in such a case short of some very aggressive optimization is to constantly branch back and forth between the implementation of, say, map, and the closure you provided, and likewise transmit data across these disparate branches of code (through registers and stack, typically).

That kind of branching/calling overhead is very difficult for the optimizer to eliminate, especially given the flexibility of Swift's closures (not impossible but conceptually quite difficult). C++ optimizers can inline function object calls but with far more restrictions and code generation techniques required to do it where the compiler would effectively have to generate a whole new set of instructions for map for each type of function object you pass in (and with explicit aid of the programmer indicating a function template used for the code generation).

So it shouldn't be of great surprise to find that your hand-rolled loops can perform faster -- they put a great deal of less strain on the optimizer. I have seen some people cite that these higher-order functions should be able to go faster as a result of the vendor being able to do things like parallelize the loop, but to effectively parallelize the loop would first require the kind of information that would typically allow the optimizer to inline the nested function calls within to a point where they become as cheap as the hand-rolled loops. Otherwise the function/closure implementation you pass in is going to be effectively opaque to functions like map/reduce: they can only call it and pay the overhead of doing so, and cannot parallelize it since they cannot assume anything about the nature of the side effects and thread-safety in doing so.

Of course this is all conceptual -- Swift may be able to optimize these cases in the future, or it may already be able to do so now (see -Ofast as a commonly-cited way to make Swift go faster at the cost of some safety). But it does place a heavier strain on the optimizer, at the very least, to use these kinds of functions over the hand-rolled loops, and the time differences you're seeing in the first benchmark seem to reflect the kind of differences one might expect with this additional calling overhead. Best way to find out is to look at the assembly and try various optimization flags.

Standard Functions

That's not to discourage the use of such functions. They do more concisely express intent, they can boost productivity. And relying on them could allow your codebase to get faster in future versions of Swift without any involvement on your part. But they aren't necessarily always going to be faster -- it is a good general rule to think that a higher-level library function that more directly expresses what you want to do is going to be faster, but there are always exceptions to the rule (but best discovered in hindsight with a profiler in hand since it's far better to err on the side of trust than distrust here).

Artificial Benchmarks

As for your second benchmark, it is almost certainly a result of the compiler optimizing away code that has no side effects that affect user output. Artificial benchmarks have a tendency to be notoriously misleading as a result of what optimizers do to eliminate irrelevant side effects (side effects that don't affect user output, essentially). So you have to be careful there when constructing benchmarks with times that seem too good to be true that they aren't the result of the optimizer merely skipping all the work you actually wanted to benchmark. At the very least, you want your tests to output some final result gathered from the computation.

Answer from user4842163 on Stack Overflow
🌐
Medium
medium.com › @armanabkar › map-filter-and-reduce-in-swift-e97558c21c89
Map, Filter, and Reduce in Swift. Higher-Order Functions such as map… | by Arman | Medium
January 5, 2022 - let nums = [2.0, 4.0, 5.0] var total = nums.reduce(10.0) { (result, el) in return result + el // 21.0 } total = nums.reduce(10.0, +) // 21.0 - simplified using + These are variations on the map method that flatten or compact the result. flatMap is used to map and then flatten a collection of collections: let nums = [[4, 3], [9, 6, 4], [2]] let allNums = nums.flatMap { $0 } // [4, 3, 9, 6, 4, 2] let certainNums = nums.flatMap { $0.filter { $0 > 5} } // [9, 6] In Swift 3, this was also used for removing nil values from the collection.
🌐
Use Your Loaf
useyourloaf.com › blog › swift-guide-to-map-filter-reduce
Swift Guide to Map Filter Reduce
May 1, 2018 - With that in mind here is my guide to using map, filter, reduce (and flatMap and compactMap). ... Use map to loop over a collection and apply the same operation to each element in the collection.
🌐
Waldo
waldo.com › home › learn › mobile › understanding higher-order functions in swift
Understanding map, filter, reduce in Swift
January 27, 2026 - This article explains higher-order functions in Swift, showing how map, filter, reduce, and closures help transform and aggregate data cleanly.
Top answer
1 of 4
40

Shouldn't the built-in Array methods be faster than the naive approach for performing such operations? Maybe somebody with more low-level knowledge than I can shed some light on the situation.

I just want to attempt to address this part of the question and more from the conceptual level (with little understanding of the nature of Swift's optimizer on my part) with a "not necessarily". It's coming more from a background in compiler design and computer architecture than deep-rooted knowledge of the nature of Swift's optimizer.

Calling Overhead

With functions like map and reduce accepting functions as inputs, it places a greater strain on the optimizer to put it one way. The natural temptation in such a case short of some very aggressive optimization is to constantly branch back and forth between the implementation of, say, map, and the closure you provided, and likewise transmit data across these disparate branches of code (through registers and stack, typically).

That kind of branching/calling overhead is very difficult for the optimizer to eliminate, especially given the flexibility of Swift's closures (not impossible but conceptually quite difficult). C++ optimizers can inline function object calls but with far more restrictions and code generation techniques required to do it where the compiler would effectively have to generate a whole new set of instructions for map for each type of function object you pass in (and with explicit aid of the programmer indicating a function template used for the code generation).

So it shouldn't be of great surprise to find that your hand-rolled loops can perform faster -- they put a great deal of less strain on the optimizer. I have seen some people cite that these higher-order functions should be able to go faster as a result of the vendor being able to do things like parallelize the loop, but to effectively parallelize the loop would first require the kind of information that would typically allow the optimizer to inline the nested function calls within to a point where they become as cheap as the hand-rolled loops. Otherwise the function/closure implementation you pass in is going to be effectively opaque to functions like map/reduce: they can only call it and pay the overhead of doing so, and cannot parallelize it since they cannot assume anything about the nature of the side effects and thread-safety in doing so.

Of course this is all conceptual -- Swift may be able to optimize these cases in the future, or it may already be able to do so now (see -Ofast as a commonly-cited way to make Swift go faster at the cost of some safety). But it does place a heavier strain on the optimizer, at the very least, to use these kinds of functions over the hand-rolled loops, and the time differences you're seeing in the first benchmark seem to reflect the kind of differences one might expect with this additional calling overhead. Best way to find out is to look at the assembly and try various optimization flags.

Standard Functions

That's not to discourage the use of such functions. They do more concisely express intent, they can boost productivity. And relying on them could allow your codebase to get faster in future versions of Swift without any involvement on your part. But they aren't necessarily always going to be faster -- it is a good general rule to think that a higher-level library function that more directly expresses what you want to do is going to be faster, but there are always exceptions to the rule (but best discovered in hindsight with a profiler in hand since it's far better to err on the side of trust than distrust here).

Artificial Benchmarks

As for your second benchmark, it is almost certainly a result of the compiler optimizing away code that has no side effects that affect user output. Artificial benchmarks have a tendency to be notoriously misleading as a result of what optimizers do to eliminate irrelevant side effects (side effects that don't affect user output, essentially). So you have to be careful there when constructing benchmarks with times that seem too good to be true that they aren't the result of the optimizer merely skipping all the work you actually wanted to benchmark. At the very least, you want your tests to output some final result gathered from the computation.

2 of 4
17

I cannot say much about your first test (map() vs append() in a loop) but I can confirm your results. The append loop becomes even faster if you add

output.reserveCapacity(array.count)

after the array creation. It seems that Apple can improve things here and you might file a bug report.

In

for _ in 0..<100_000 {
    var sum: Float = 0
    for element in array {
        sum += element
    }
}

the compiler (probably) removes the entire loop because the computed results are not used at all. I can only speculate why a similar optimization does not happen in

for _ in 0..<100_000 {
    let sum = array.reduce(0, combine: {1})
}

but it would more difficult to decide if calling reduce() with the closure has any side-effects or not.

If the test code is changed slightly to calculate and print a total sum

do {
    var total = Float(0.0)
    let start = NSDate()
    for _ in 0..<100_000 {
        total += array.reduce(0, combine: {1})
    }
    let elapsed = NSDate().timeIntervalSinceDate(start)
    print("sum with reduce:", elapsed)
    print(total)
}

do {
    var total = Float(0.0)
    let start = NSDate()
    for _ in 0..<100_000 {
        var sum = Float(0.0)
        for element in array {
            sum += element
        }
        total += sum
    }
    let elapsed = NSDate().timeIntervalSinceDate(start)
    print("sum with loop:", elapsed)
    print(total)
}

then both variants take about 10 seconds in my test.

🌐
Appy Pie Vibe
appypievibe.ai › home › app development › map, reduce and filter in swift
Map, Reduce and Filter in Swift – Appy Pie Vibe
November 11, 2020 - ... The map() function applies a function to every item in a collection. Think of “mapping” or transforming one set of values into another set of values. The reduce() function turns a collection into one value.
🌐
Swift Forums
forums.swift.org › evolution › pitches
Adding an index with functional methods like map, reduce, filter - Pitches - Swift Forums
June 17, 2018 - Here's a quick draft pitch before I can expand on it. The gist is to add an index to the functional methods, so it can allow for something like (note mapi is used to differentiate it from map) let arrayNumbers = [1, 2, 3, 4, 5, 6] let oddOnes = arrayNumbers.mapi{(number, index) in if index % 2 == 0 { return number } else { return number * 2 } } in case of reduce, filter etc it can be used in a similar fashion where the index helps to eliminate loops that would ot...
🌐
Bugfender
bugfender.com › blog › swift-arrays
Swift Arrays: Map, Filter, Reduce & Sort Explained | Bugfender
November 7, 2025 - This combines the inner array of the original map into one single array, removing any nested Collections or multidimensional arrays. Reduce is the final higher-order function we’ll cover today.
🌐
GitHub
gist.github.com › SheldonWangRJT › 791c85749051cf4b63b1590f08143156
Swift Map, FlatMap (CompactMap), Reduce, Filter & Sort · GitHub
Therefore, Apple tries to clarify the naming to make only use flatMap/compactMap when it is really needed. Reduce is to take all elements for calculations let numbers: [Int] = [2, 4, 1, 3]
Find elsewhere
🌐
Reintech
reintech.io › blog › swift-map-reduce-filter-tutorial
How to use Swift's map, reduce, and filter functions | Reintech media
October 6, 2023 - This function is highly useful in data manipulation tasks and can help improve code efficiency and readability. The reduce function in Swift is used to combine all elements of a collection into a single output value.
🌐
SKOUMAL
skoumal.com › blog › performance of built-in higher-order functions map, filter, reduce, and flatmap vs. for-in loop in swift
Performance of Map, Filter, Reduce, and flatMap vs. for-in loop in Swift
December 22, 2023 - In other words, in the worst case, the result of filter function can be O(n), which means nothing was filtered out and this result is used as input of reduce function. In the end, the time complexity is O(3n). However, if we use a for-in loop we can do all necessary things (map.
🌐
Brightec
brightec.co.uk › home › blog › how to filter, map, and reduce in swift
Swift Basics: Mapping, Filtering, and Reducing in Swift |… | Brightec
August 16, 2023 - Swift’s map, filter, and reduce functions are often referred to as higher-order functions. This is because they take a function as an input and return it as an output. Using map, filter, and reduce in Swift results in clean, concise code that is more readable and offers better results.
🌐
Medium
abhimuralidharan.medium.com › higher-order-functions-in-swift-filter-map-reduce-flatmap-1837646a63e8
Higher order functions in Swift: Filter, Map, Reduce, flatmap, compactMap | by Abhimuralidharan | Medium
May 22, 2024 - Higher order functions in Swift: Filter, Map, Reduce, flatmap, compactMap Ever since I learned about functions and closures in detail, I wanted to know more about the advantages and usages of these …
🌐
YouTube
youtube.com › watch
Filter, Map, Reduce, CompactMap, FlatMap - Swift - iOS Dev Interview Questions - YouTube
Go to https://squarespace.com/seanallen to save 10% off your first purchase of a website or domain using code SEANALLEN. Explaining Filter, Map and Reduce in...
Published   February 24, 2023
🌐
Swiftunboxed
swiftunboxed.com › lang › reduce
Reduce - Swift Unboxed
5 April 2017 ∙ Swift Language ∙ written by Greg Heo · Filter, reduce, and map: Collections transformed at a tap.
🌐
DEV Community
dev.to › eleazar0425 › map-filter-and-reduce-in-swift-mbk
Map, Filter and Reduce in Swift - DEV Community
June 16, 2020 - Okay, that sounds too technical. Let me explain it in other words. What reduce function does is to combine every item of a collection in a unique value.
Top answer
1 of 3
1

You are multiplying doubles in the first part of the calc and everything in the calc should be Doubles. It works if you "initialise" the Int as a double, eg.

Double($0.quantity)

The maths works fine in playgrounds with this. It also is better to leave spaces around the operators also as I had a couple of flags on this.

class EmbeddedElement  {
var totalPrice: Double = 5.0
var discount: Double = 3.2
var quantity: Int = 1
}

let element = EmbeddedElement()

var array = Array(repeatElement(element, count: 500))

let sum = array.map {
    ($0.totalPrice - ($0.totalPrice*$0.discount / 100)) * Double($0.quantity)
}.reduce(0,+)

With the static 5 in the second calc that works because it knows the calc is doubles and the result will be a double, so it effectively "initialises" the 5 as a double.

When dealing with prices and money you may want to look in to Decimal type as you can see with my simple example, doubles can lead to long decimal places and need for rounding which can cause minor discrepancies over a lot of values.

I guess the error you are seeing was vague as it is pretty complicated and the type system is struggling to provide something meaningful.

2 of 3
1

I think the code in the question is mostly correct. I cannot guarantee the math equation is right, but the code is sound. Here's how to troubleshoot

Take your initial code

Text("\((myElementsList.map({($0.totalPrice-($0.totalPrice*$0.discount/100))*$0.quantity}).reduce(0,+)), specifier: "%.2f") dollar ")

Let's break it down a bit into pieces so it can be examined, remove the formula, leaving the text formatting code

Text("\((    ), specifier: "%.2f") dollar ")

and then the equation

let y = myElementsList.map({($0.totalPrice-($0.totalPrice*$0.discount/100))*$0.quantity}).reduce(0,+))

ah - now issue is obvious; the error is multiplying a double by an Int as mentioned in my comment. Fixing the equation is easy! Cast the Int to a Double and then the calculation works.

let y = myElementsList.map({($0.totalPrice-($0.totalPrice*$0.discount/100))*Double($0.quantity)}).reduce(0,+)

Not too complex!

Then insert that back into the Text code

Text("\((y), specifier: "%.2f") dollar ")

And it works.

Note:

See the comment about using Doubles from currency in Hongtron's answer and my followup comment. Use Decimal128.

print(1.03 - 0.42)

outputs:

0.6100000000000001     (this is inaccurate!)

whereas

let a = Decimal128(floatLiteral: 1.03)
let b = Decimal128(floatLiteral: 0.42)
let c = a - b
print(c.decimalValue)

outputs:

0.61  (good!)
🌐
freeCodeCamp
freecodecamp.org › news › a-behind-the-scenes-look-at-map-filter-and-reduce-in-swift-1991f5c7bc80
A behind the scenes look at Map, Filter, and Reduce in Swift
December 5, 2018 - In Swift, we play with map, filter, reduce everyday. When we use these functions, it seems like magic. At this point, you might not have an idea of what is going on behind the scenes. Map, Filter, and Reduce work through the ideas and approaches of functional programming.
🌐
Apple Developer
developer.apple.com › forums › thread › 128655
syntax of the reduce method in Swift
This writing is the result of a series of implicit declaration, thanks to the smart Swift compiler. Let's look how we go from the most extensive form to the very short one. Test it all in playground, to see it working. ... and finally, when closure is inside (), as arguments $0 and $1 can be deduced, we can just write the shortest form: ... Imagine now you want to sum the squares; the compact form does not work. ... But you could also first map the array to the squares, and use the compact reduce !