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 创建惰性无限序列,而不是 mapping 一个范围。

map 将每个元素从其类型转换为其他类型,以便转换需要闭包中的参数。但为了方便起见,您可以通过扩展 RangeClosedRange:

来省略此参数
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]