在数组中查找所有元素实例的索引

3
这个问题很简单。在Swift中有没有一种方法可以找到数组中一个元素的所有出现位置,而不需要通过循环来实现?似乎所有内置方法都只返回第一个出现的索引,而不是所有的索引。
最好有一种类似于index(where:)的方法,它返回一个索引数组。有什么想法吗?
提前感谢您的任何回复!
编辑:
谢谢大家的回复!看起来我应该更清楚地表达这个问题。我目前正在使用的是一个扩展,它看起来与Matt下面发布的扩展非常相似。我知道任何实现这个功能的方法都必须在底层循环遍历数组,我更想知道是否有一个内置方法隐藏在语言中,我不知道。这似乎是人们通常想做的事情。看来这个扩展将继续存在!

3
有没有办法在Swift中找到数组中一个元素的所有出现位置而无需使用循环?回答是:没有!如果有内置函数可以实现这一功能,那么它也需要进行循环操作。 - undefined
一个框架是对长代码的封装,创建一个数组扩展并在任何地方使用它。 - undefined
3个回答

9
有没有一种方法在Swift中找到数组中所有元素的出现,而不需要通过循环来实现?
显然不行。没有魔法可以一次性查看整个数组。
你不必自己进行循环,但无论你做什么,你至少要请求Swift为你遍历数组。不管是你还是Swift,都必须进行循环。
例如,这可能看起来优雅而简洁:
    let arr = [1, 2, 3, 1, 0, 1, 2, 2, 3, 1, 1, 2]
    let target = 1
    let indices = arr.enumerated().reduce(into: []) {
        if $1.1 == target {$0.append($1.0)}
    }
    // indices is [0, 3, 5, 9, 10]

...但是猜猜reduce做了什么?它循环。


顺便说一句,我建议将这种东西封装为通用扩展:

extension Collection where Element : Equatable {
    func allIndices(of target:Element) -> [Int] {
        let indices = self.enumerated().reduce(into: [Int]()) {
            if $1.1 == target {$0.append($1.0)}
        }
        return indices
    }
}

那么,您可以随时使用以下方式谈论所有索引:
let arr = [1, 2, 3, 1, 0, 1, 2, 2, 3, 1, 1, 2]
let indices = arr.allIndices(of: 1)

@Sh_Khan 我们怎么知道呢? - undefined
他询问是否存在类似于 index(where:) 的东西。 - undefined
1
使用元组命名可以提高可读性。如果 $1.element 等于 target,则将 $1.offset 添加到 $0 中。 - undefined
1
func allIndices(of target: Element) -> [Index] { return indices.filter({ self[$0] == target }) } - undefined
1
请注意,如果您在使用此方法时将其应用于字符串,则使用“枚举”将返回一个“Int”而不是“String.Index”。 - undefined
显示剩余4条评论

4
我建议以下方式:
let arr = [1, 2, 3, 1, 0, 1, 2, 2, 3, 1, 1, 2]
let search = 1
let indices = arr.enumerated().flatMap { $1 == search ? $0 : nil }
print(indices)

[0, 3, 5, 9, 10]


但是公平地说,这种方法与手动循环遍历“枚举”对并自行累积找到的匹配索引相比,并没有任何优势。 - undefined
请注意,此返回的是偏移量而不是索引。当应用于数组的切片时,很容易被错误使用。您应该始终使用集合的索引进行操作。 - undefined

3
您可以创建自己的索引方法,该方法接受谓词作为参数: Xcode 11 • Swift 5.1
extension Collection where Element: Equatable {
    func indices(of element: Element) -> [Index] { indices.filter { self[$0] == element } }
}

extension Collection {
    func indices(where isIncluded: (Element) throws -> Bool) rethrows -> [Index] { try indices.filter { try isIncluded(self[$0]) } }
}

let arr = [1, 2, 3, 1, 0, 1, 2, 2, 3, 1, 1, 2]
let search = 1

let indices = arr.indices(where: { $0 == search })
// or simply
// let indices = arr.indices { $0 == search }
print(indices)   // [0, 3, 5, 9, 10]

let indices2 = arr.indices(of:  search)
print(indices2)   // [0, 3, 5, 9, 10]

let string = "Hello World !!!"
let indices3 = string.indices(of: "o")
print(indices3)  //  [Swift.String.Index(_compoundOffset: 16, _cache: Swift.String.Index._Cache.character(1)), Swift.String.Index(_compoundOffset: 28, _cache: Swift.String.Index._Cache.character(1))]

1
我非常喜欢这种方法。使用闭包来提供对过程的精细控制是个好主意。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接