MH1*_*175 4 arrays generics reduce swift
斯威夫特3
尝试编写一个通用数组扩展,获取不等于值的项的所有索引
例
let arr: [String] = ["Empty", "Empty", "Full", "Empty", "Full"]
let result: [Int] = arr.indexes(ofItemsNotEqualTo item: "Empty")
//returns [2, 4]
Run Code Online (Sandbox Code Playgroud)
我试图制作一个通用函数:
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
}
}
Run Code Online (Sandbox Code Playgroud)
但是这会发出警告:二进制运算符不能应用于"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
}
}
Run Code Online (Sandbox Code Playgroud)
但现在似乎类型检查已经消失了,因为如果我传入一个整数,我得到错误的结果
let arr: [String] = ["Empty", "Empty", "Full", "Empty", "Full"]
let result: [Int] = arr.indexes(ofItemsNotEqualTo item: 100)
//returns [0, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
非常感谢帮助.
使用reduce函数有更好的方法吗?
您已经定义了一个通用方法
func indexes<T: Equatable>(ofItemsNotEqualTo item: T) -> [Int]?
Run Code Online (Sandbox Code Playgroud)
它接受一个类型的参数,该参数T是必需的
Equatable,但与Element数组的类型无关.
因此
let arr = ["Empty", "Empty", "Full", "Empty", "Full"]
let result = arr.indexes(ofItemsNotEqualTo: 100)
Run Code Online (Sandbox Code Playgroud)
编译,但elem as? T给所有数组元素nil(即!= item).
你想要的是一个只为Equatable元素数组定义的方法
.这可以通过约束扩展来实现:
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
}
}
Run Code Online (Sandbox Code Playgroud)
实际上我不会将返回值设为可选.如果所有元素都等于给定项,则逻辑返回值将为空数组.
使用reduce函数有更好的方法吗?
好吧,您可以使用reduce(),但这不是非常有效,因为在每个迭代步骤中都会创建中间数组:
extension Array where Element: Equatable {
func indexes(ofItemsNotEqualTo item: Element) -> [Int] {
return enumerated().reduce([]) {
$1.element == item ? $0 : $0 + [$1.offset]
}
}
}
Run Code Online (Sandbox Code Playgroud)
你实际拥有的是"过滤器+地图"操作:
extension Array where Element: Equatable {
func indexes(ofItemsNotEqualTo item: Element) -> [Int] {
return enumerated().filter { $0.element != item }.map { $0.offset }
}
}
Run Code Online (Sandbox Code Playgroud)
可以简化使用flatMap():
extension Array where Element: Equatable {
func indexes(ofItemsNotEqualTo item: Element) -> [Int] {
return enumerated().flatMap { $0.element != item ? $0.offset : nil }
}
}
Run Code Online (Sandbox Code Playgroud)
例子:
let arr = ["Empty", "Empty", "Full", "Empty", "Full"]
arr.indexes(ofItemsNotEqualTo: "Full") // [0, 1, 3]
[1, 1, 1].indexes(ofItemsNotEqualTo: 1) // []
arr.indexes(ofItemsNotEqualTo: 100)
// error: cannot convert value of type 'Int' to expected argument type 'String'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2685 次 |
| 最近记录: |