The Missing Array.appending(contentsOf:)
The Swift standard library has a mutating func append(contentsOf:)
, but not an immutable variant.
Usually, the Array
and Collection
types offer both. I wonder why that’s not the case here. To be fair, the concatenation operator +
does the same trick.
Here’s a basic implementation I’m using in my apps since forever, but which I haven’t shared, and which I never bothered to store in my code snippets repository (maybe because I believed that this would surely soon be added):
extension Array {
public func appending(contentsOf other: Array<Element>) -> Array<Element> {
var result = self
result.append(contentsOf: other)
return result
}
}
But that’s not very elegant or generic.
Here’s how to find a better base type:
Searching for appending(contentsOf:)
in the Swift documentation, a couple of results pop up: Array
, ArraySlice
, ContiguousArray
, Data
, RangeReplaceableCollection
, Slice
, String
, Substring
, and a couple others even further removed from an array.
So RangeReplaceableCollection
is the most generic one I found that would do the trick. Sequence
and Collection
don’t offer append(contentsOf:)
, so these are all out.
Checking out append(contentsOf:)
will reveal that the parameter can be any Sequence
as long as it has the same Element
type, which is nice for additional flexibility.
The result is this:
extension RangeReplaceableCollection {
public func appending<Other>(contentsOf other: Other) -> Self
where Other: Sequence, Other.Element == Element {
var result = self
result.append(contentsOf: other)
return result
}
}
That is a drop-in replacement for the Array
extension from above, but unlike that, this will also work on String
s and Data
etc. as well!
Like the concatenation operator +
, this works on mixed left and right hand sides:
"abc".appending(contentsOf: ["d", "e", "f"])