arrays – Swift泛型数组函数,用于查找不匹配项的元素的所有索引

斯威夫特3

尝试编写一个通用数组扩展,获取不等于值的项的所有索引

let arr: [String] = ["Empty","Empty","Full","Full"]
 let result: [Int] = arr.indexes(ofItemsNotEqualTo item: "Empty")
 //returns [2,4]

我试图制作一个通用函数

extension Array {

    func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?  {
        var result: [Int] = []
        for (n,elem) in self.enumerated() {
            if elem  != item {
                result.append(n)
            }
        }
        return result.isEmpty ? nil : result
    }
}

但是这会发出警告:二进制运算符不能应用于“Element”和“T”类型的操作数.

所以我在这里投了元素(注意为?)

extension Array {

    func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?  {
        var result: [Int] = []
        for (n,elem) in self.enumerated() {
            if elem as? T != item {
                result.append(n)
            }
        }
        return result.isEmpty ? nil : result
    }
}

但现在似乎类型检查已经消失了,因为如果我传入一个整数,我得到错误的结果

let arr: [String] = ["Empty","Full"]
 let result: [Int] = arr.indexes(ofItemsNotEqualTo item: 100)
 //returns [0,1,2,3,4]

非常感谢帮助.

使用reduce函数有更好的方法吗?

解决方法

您已经定义了一个通用方法

func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?

它采用类型为T的参数
Equatable,但与数组的Element类型无关.

因此

let arr = ["Empty","Full"]
let result = arr.indexes(ofItemsNotEqualTo: 100)

编译,但是作为? T给出nil(这是!=项目)
对于所有数组元素.

你想要的是一个只为数组定义的方法
等同的元素.这可以通过约束来实现
延期:

extension Array where Element: Equatable {
    func indexes(ofItemsNotEqualTo item: Element) -> [Int]?  {
        var result: [Int] = []
        for (n,elem) in enumerated() {
            if elem != item {
                result.append(n)
            }
        }
        return result.isEmpty ? nil : result
    }
}

实际上我不会将返回值设为可选.
如果所有元素都等于给定项,那么逻辑
返回值将是空数组.

Is there a better way to do this with the reduce function?

好吧,您可以使用reduce(),但这不是非常有效,因为在每个迭代步骤中都会创建中间数组:

extension Array where Element: Equatable {
    func indexes(ofItemsNotEqualTo item: Element) -> [Int]  {
        return enumerated().reduce([]) {
            $1.element == item ? $0 : $0 + [$1.offset]
        }
    }
}

你实际拥有的是一个
“过滤地图”操作:

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

可以使用flatMap()简化:

extension Array where Element: Equatable {

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

例子:

let arr = ["Empty","Full"]
arr.indexes(ofItemsNotEqualTo: "Full") // [0,3]

[1,1].indexes(ofItemsNotEqualTo: 1) // []

arr.indexes(ofItemsNotEqualTo: 100)
// error: cannot convert value of type 'Int' to expected argument type 'String'

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...