'How can I process this array more efficiently

I have an array of names that looks like the following. ["John Doe", "Mary Blog"]

What I want to do is process this array and return an array with the initials like the following.

["JD", "MB"]

I have already done this but my code is ugly and inefficient (nested loops). It's probably fine for a small array like in my example.

How can I process my array more efficiently?

       let contacts = ["John Doe", "Mary Blog"]
       var initalsArray: [String] = []
       let names = contacts.map {$0}

            for name in names {
                var initals: String = ""
                let fullname = name.components(separatedBy: " ")
                for part in fullname {
                    if part.count > 0 {
                        initals += part[0]
                    }
                }
                initalsArray.append(initals)
            }


Solution 1:[1]

You must process all elements in the array.

For every element, you must detect the spaces and retrieve the next letter.

Then you must build up the output array with concatenated capitals.

So I really don't see how you could avoid a double loop.

Only if part.count > 0 is unnecessary.


Alternatively, you can scan the strings yourself to avoid generating the intermediate array fullname.

You can probably also obtain the result by regex processing, but this would be a sledgehammer to crack nuts. Don't.


A possible implementation of the inner loop. (Sorry if this is invalid, I don't know Swift).

var space: Bool = true
for c in name {
  if space && c != ' ' {
    initials+= c
  } 
  space= c == ' '
}

Notice that the (optional) extra condition c != ' ' protects against double spaces.

Solution 2:[2]

You can use map to remove some of your own looping

let contacts = ["John Doe", "Mary Blog"]
let result = contacts.map { $0.components(separatedBy: .whitespacesAndNewlines).map { String($0.prefix(1)) }.joined(separator: "") }
print(result)

I don't known if this is any quicker, maybe it gives Apple a chance to fro some optimisation that is hard to do

Solution 3:[3]

Actually this answer though similar may be a bit quicker

let contacts = ["John Doe", "Mary Blog"]
let result = contacts.map { $0.components(separatedBy: .whitespacesAndNewlines).reduce("") { $0 + String($1.prefix(1)) } }
print(result)

Instated of constructing inner arrays and then joining them I just added it to the string of previous first letters

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3