Swift 没有 $0 的数组映射(高阶函数)
Swift array map without $0 (Higher-Order Functions )
我有一个函数可以在某些条件下生成数字
func randomWithCondition() -> Int {
...
return n
}
稍后我会在另一个函数中使用这个函数构建一个长度为N的数组
func a() -> [Int] {
var arr = [Int]()
for _ in 0..<length {
arr.append(randomWithCondition())
}
return arr
}
我想把这些写成一行,我能想到的最好的是
return (0..<N).map { _ in randomWithCondition() }
因为没用[=15=]
所以要加上_ in
,不然编译不通过
问:有没有绕过不写_ in
?任何其他格式都可以,只要它是 return 语句中的一行即可。
你需要自己定义一些额外的函数。
例如,一个const
函数(名称的灵感来自Haskell,但您可以将其称为withParameter
):
func const<T, U>(_ f: @escaping () -> U) -> ((T) -> U) {
{ _ in f() }
}
那么你可以这样做:
return (0..<N).map(const(randomWithCondition))
我想你也应该把它包装在一个 generate
函数中:
func generate<T>(_ count: Int, generator: @escaping () -> T) -> [T] {
(0..<count).map(const(generator))
}
请注意,您还可以使用 sequence
创建惰性无限序列,而不是 map
ping 一个范围。
map
将每个元素从其类型转换为其他类型,以便转换需要闭包中的参数。但为了方便起见,您可以通过扩展 Range
和 ClosedRange
:
来省略此参数
extension Range where Bound: Strideable, Bound.Stride: SignedInteger {
public func map<T>(_ transform: () -> T) -> [T] {
map { _ in transform() }
}
}
extension ClosedRange where Bound: Strideable, Bound.Stride: SignedInteger {
public func map<T>(_ transform: () -> T) -> [T] {
map { _ in transform() }
}
}
let range = (0..<10).map { arc4random() }
print(range)
// Outputs: [676946806, 482060909, 1553829324, 1660236508, 606395000, 268649066, 1438948568, 1995527535, 918698113, 505678702]
let closedRange = (0...9).map { arc4random() }
print(closedRange)
// Outputs: [20467139, 198204705, 1585520963, 2022302907, 2518334206, 3304761403, 3782378335, 3830286797, 2200585433, 2387902936]
我有一个函数可以在某些条件下生成数字
func randomWithCondition() -> Int {
...
return n
}
稍后我会在另一个函数中使用这个函数构建一个长度为N的数组
func a() -> [Int] {
var arr = [Int]()
for _ in 0..<length {
arr.append(randomWithCondition())
}
return arr
}
我想把这些写成一行,我能想到的最好的是
return (0..<N).map { _ in randomWithCondition() }
因为没用[=15=]
所以要加上_ in
,不然编译不通过
问:有没有绕过不写_ in
?任何其他格式都可以,只要它是 return 语句中的一行即可。
你需要自己定义一些额外的函数。
例如,一个const
函数(名称的灵感来自Haskell,但您可以将其称为withParameter
):
func const<T, U>(_ f: @escaping () -> U) -> ((T) -> U) {
{ _ in f() }
}
那么你可以这样做:
return (0..<N).map(const(randomWithCondition))
我想你也应该把它包装在一个 generate
函数中:
func generate<T>(_ count: Int, generator: @escaping () -> T) -> [T] {
(0..<count).map(const(generator))
}
请注意,您还可以使用 sequence
创建惰性无限序列,而不是 map
ping 一个范围。
map
将每个元素从其类型转换为其他类型,以便转换需要闭包中的参数。但为了方便起见,您可以通过扩展 Range
和 ClosedRange
:
extension Range where Bound: Strideable, Bound.Stride: SignedInteger {
public func map<T>(_ transform: () -> T) -> [T] {
map { _ in transform() }
}
}
extension ClosedRange where Bound: Strideable, Bound.Stride: SignedInteger {
public func map<T>(_ transform: () -> T) -> [T] {
map { _ in transform() }
}
}
let range = (0..<10).map { arc4random() }
print(range)
// Outputs: [676946806, 482060909, 1553829324, 1660236508, 606395000, 268649066, 1438948568, 1995527535, 918698113, 505678702]
let closedRange = (0...9).map { arc4random() }
print(closedRange)
// Outputs: [20467139, 198204705, 1585520963, 2022302907, 2518334206, 3304761403, 3782378335, 3830286797, 2200585433, 2387902936]