Swift - How to get indexes of filtered items of array
You can filter the indices
of the array directly, it avoids the extra map
ping.
let items = ["A", "B", "A", "C", "A", "D"]let filteredIndices = items.indices.filter {items[$0] == "A"}
or as Array
extension:
extension Array where Element: Equatable { func whatFunction(_ value : Element) -> [Int] { return self.indices.filter {self[$0] == value} }}items.whatFunction("A") // -> [0, 2, 4]items.whatFunction("B") // -> [1]
or still more generic
extension Collection where Element: Equatable { func whatFunction(_ value : Element) -> [Index] { return self.indices.filter {self[$0] == value} }}
You can create your own extension for arrays.
extension Array where Element: Equatable { func indexes(of element: Element) -> [Int] { return self.enumerated().filter({ element == $0.element }).map({ $0.offset }) }}
You can simply call it like this
items.indexes(of: "A") // [0, 2, 4]items.indexes(of: "B") // [1]
You can achieve this by chain of:
enumerated()
- add indexes;filter()
out unnecessary items;map()
our indexes.
Example (works in Swift 3 - Swift 4.x):
let items: [String] = ["A", "B", "A", "C", "A", "D"] print(items.enumerated().filter({ $0.element == "A" }).map({ $0.offset })) // -> [0, 2, 4]
Another way is using flatMap
, which allows you to check the element and return index if needed in one closure.
Example (works in Swift 3 - Swift 4.0):
print(items.enumerated().flatMap { $0.element == "A" ? $0.offset : nil }) // -> [0, 2, 4]
But since Swift 4.1 flatMap
that can return non-nil objects become deprecated and instead you should use compactMap
.
Example (works since Swift 4.1):
print(items.enumerated().compactMap { $0.element == "A" ? $0.offset : nil }) // -> [0, 2, 4]
And the cleanest and the most memory-cheap way is to iterate through array indices and check if element of array at current index equals to required element.
Example (works in Swift 3 - Swift 4.x):
print(items.indices.filter({ items[$0] == "A" })) // -> [0, 2, 4]