I have the desired output using a loop today but how can I exchange this loop with a one line expression using map and filter?
I start with an array of countries. From this one I generate a second array with the initial letters using map. I would now like to build a 2D-array that contains all the countries with the same initial letter in separate arrays using map and filter so that I can get rid of the loop I use today.
let countries = ["Albania", "Algeria", "Angola", "Bahamas", "Bahrain", "Canada"]
var initials = Set(countries.map { $0.prefix(1) }).sorted()
func countriesByInitial() -> [[String]] {
var result = [[String]]()
for initial in initials {
result.append(countries.filter { $0.prefix(1) == initial })
}
return result
}
You can achieve it by group > sort > map combination as:
let countries = ["Algeria", "Albania", "Belarus", "Bahamas", "Canada"]
let groupedDict = Dictionary(grouping: countries, by: { $0.prefix(1) })
let sortedDict = groupedDict.sorted(by: { $0.key < $1.key })
let arr2D = sortedDict.map({ $0.value })
You can write it in a single line:
let arr = (Dictionary(grouping: countries, by: { $0.prefix(1) })).sorted(by: { $0.key < $1.key }).map({ $0.value })
You can use reduce on array as well:
// $0 will be of type [[String]]
// $1 will be of type String
let arr2D: [[String]] = countries.reduce(into: []) {
let checkChar = $1.first
if let idx = $0.index(where: {$0.first?.first == checkChar }) {
$0[idx].append($1)
} else {
$0.append([$1])
}
}
You can use Swift 4 method reduce(into:) if your array it is already sorted, otherwise you just need to sort it before grouping it:
let countries = ["Albania", "Algeria", "Angola", "Bahamas", "Bahrain", "Canada"]
let grouped: [[String]] = countries.reduce(into: []) {
if $0.last?.last?.prefix(1) == $1.prefix(1) {
$0[$0.index(before: $0.endIndex)].append($1)
} else {
$0.append([$1])
}
}
print(grouped) // [["Albania", "Algeria", "Angola"], ["Bahamas", "Bahrain"], ["Canada"]]\n"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With