Swift - Как получить индексы фильтрованных элементов массива

let items: [String] = ["A", "B", "A", "C", "A", "D"]

items.whatFunction("A") // -> [0, 2, 4]
items.whatFunction("B") // -> [1]

Поддерживает ли Swift 3 такую ​​функцию, как whatFunction(_: Element)?

Если нет, то какая наиболее эффективная логика?

Ответ 1

Вы можете создать собственное расширение для массивов.

extension Array where Element: Equatable {
    func indexes(of element: Element) -> [Int] {
        return self.enumerated().filter({ element == $0.element }).map({ $0.offset })
    }
}

Вы можете просто называть это следующим образом

items.indexes(of: "A") // [0, 2, 4]
items.indexes(of: "B") // [1]

Ответ 2

Вы можете напрямую фильтровать indices массива, это исключает дополнительный пинг map.

let items = ["A", "B", "A", "C", "A", "D"]
let filteredIndices = items.indices.filter {items[$0] == "A"}

или как расширение Array:

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]

или еще более общий

extension Collection where Element: Equatable {

    func whatFunction(_ value :  Element) -> [Index] {
        return self.indices.filter {self[$0] == value}
    }

}

Ответ 3

Вы можете достичь этого с помощью цепочки:

  1. enumerated() - добавить индексы;
  2. filter() ненужные элементы;
  3. map() наши индексы.

Пример (работает в 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]

Другой способ - использовать flatMap, который позволяет проверить элемент и вернуть индекс, если необходимо, в одном замыкании.

Пример (работает в Swift 3 - Swift 4.0):

print(items.enumerated().flatMap { $0.element == "A" ? $0.offset : nil }) // -> [0, 2, 4]

Но начиная с Swift 4.1 flatMap который может возвращать объекты, отличные от nil, устарели, и вместо этого вы должны использовать compactMap.

Пример (работает с Swift 4.1):

print(items.enumerated().compactMap { $0.element == "A" ? $0.offset : nil }) // -> [0, 2, 4]

И самый чистый и самый дешевый способ - это перебирать индексы массива и проверять, равен ли элемент массива в текущем индексе требуемому элементу.

Пример (работает в Swift 3 - Swift 4.x):

print(items.indices.filter({ items[$0] == "A" })) // -> [0, 2, 4]

Ответ 4

В Swift 3 и Swift 4 вы можете сделать это:

let items: [String] = ["A", "B", "A", "C", "A", "D"]

extension Array where Element: Equatable {

    func indexes(of item: Element) -> [Int]  {
        return enumerated().compactMap { $0.element == item ? $0.offset : nil }
    }
}

items.indexes(of: "A")

Я надеюсь, что мой ответ был полезным 😊

Ответ 5

вы можете использовать его так:

 let items: [String] = ["A", "B", "A", "C", "A", "D"]

        let indexes = items.enumerated().filter {
            $0.element == "A"
            }.map{$0.offset}

        print(indexes)

Ответ 6

просто скопируйте и вставьте

extension Array {
  func whatFunction(_ ids :  String) -> [Int] {

    var mutableArr = [Int]()
    for i in 0..<self.count {
        if ((self[i] as! String) == ids) {
            mutableArr.append(i)
        }
    }
        return mutableArr 
  }

}

Ответ 7

Например, поиск индексов значений p_last в массиве inds1: (swift 4+)

let p_last = [51,42]
let inds1 = [1,3,51,42,4]
let idx1 = Array(inds1.filter{ p_last.contains($0) }.indices)

idx1 = [0,1]