Additional joined
Functions
I frequently find myself wanting to join collections whose elements do not conform to StringProtocol
. I would like to suggest the addition of some new joined
functions as extensions on Collection
.
public extension Collection where Element: CustomStringConvertible {
/// Returns a new string by concatenating the elements of the sequence, adding the given separator between each element.
///
/// The following example shows how an array of integers can be joined to a single, dash-separated string:
///
/// let phoneNumberSections = [492, 573, 5843]
/// let phoneNumber = phoneNumberSections.joined(separator: ", ")
/// print(phoneNumber)
/// // Prints "492-573-5843"
///
/// - Parameters:
/// - separator: A string to insert between each of the elements in this collection. The default separator is an empty string.
///
/// - Returns: A single, concatenated string.
///
@inlinable func joined(separator: String = "") -> String {
guard let first = first else { return "" }
guard count > 1 else { return "\(first)" }
return dropFirst().reduce(into: "\(first)") { $0.append(separator + "\($1)") }
}
}
public extension Collection {
/// Returns a new string by mapping the given closure over the collection's elements and concatenating `String` results, adding the given separator between each string.
///
/// The following example shows how an array of integers can be transformed into each integer's respective square and joined to a single string separated by addition operators:
///
/// let numbers = [1, 2, 3, 4, 5, 6, 7]
/// let sumOfSquares = numbers.joined(separator: " + ") { "\($0 * $0)" }
/// print(sumOfSquares)
/// // Prints "1 + 4 + 9 + 16 + 25 + 36 + 49"
///
/// - Parameters:
/// - separator: A string to insert between each of the elements of this collection transformed into strings. The default separator is an empty string.
/// - transform: A mapping closure that produces a string. `transform` accepts an element of this collection as its parameter and returns a transformed `String` value.
///
/// - Returns: A single, concatenated string.
///
@inlinable func joined(separator: String = "", _ transform: (Element) throws -> String) rethrows -> String {
guard let first = first else { return "" }
guard count > 1 else { return try transform(first) }
return try dropFirst().reduce(into: try transform(first)) { $0.append(separator + (try transform($1))) }
}
}
Usage
let phoneNumberSections = [492, 573, 5843]
let phoneNumber = phoneNumberSections.joined(separator: ", ")
print(phoneNumber)
// Prints "492-573-5843"
let numbers = [1, 2, 3, 4, 5, 6, 7]
let sumOfSquares = numbers.joined(separator: " + ") { "\($0 * $0)" }
print(sumOfSquares)
// Prints "1 + 4 + 9 + 16 + 25 + 36 + 49"
struct Person {
var name: String
var age: Int
}
let people = [
Person(name: "Vivien", age: 23),
Person(name: "Joseph", age: 49),
Person(name: "Marlon", age: 12)
]
let peopleStr = people.joined(separator: " and ") { "\($0.name) is \($0.age)" }
print(peopleStr)
// Prints "Vivien is 23 and Joseph is 49 and Marlon is 12"
//