gpt4 book ai didi

arrays - Swift 数组循环一次,写很多

转载 作者:搜寻专家 更新时间:2023-10-31 22:22:37 25 4
gpt4 key购买 nike

考虑以下愚蠢、简单的示例:

let arr = ["hey", "ho"]
let doubled = arr.map {$0 + $0}
let capitalized = arr.map {$0.capitalizedString}

如您所见,我以多种方式处理相同的初始数组,以便最终得到多个已处理的数组。

现在假设 arr 很长,并且我有许多这样的进程生成许多最终数组。我不喜欢上面的代码,因为我们循环多次,每次 map 调用一次。我宁愿只循环一次。

现在,显然我们可以通过蛮力来处理这个问题,即从多个可变数组开始并在每次迭代中写入所有这些数组:

let arr = ["hey", "ho"]
var doubled = [String]()
var capitalized = [String]()
for s in arr {
doubled.append(s + s)
capitalized.append(s.capitalizedString)
}

很好。但是现在我们没有得到使用 map 的乐趣。所以我的问题是:有没有更好、更快捷的方法?以一种模糊的方式,我想象自己使用 map 或类似 map 的东西来生成类似元组的东西,并在我们迭代时神奇地将元组拆分为所有结果数组,如如果我可以这样说(伪代码,不要在家里尝试):

let arr = ["hey", "ho"]
let (doubled, capitalized) = arr.map { /* ???? */ }

如果我正在设计我自己的语言,我什至可能允许通过赋值将一种溅射到左值的伪数组中:

let arr = ["hey", "ho"]
let [doubled, capitalized] = arr.map { /* ???? */ }

做不成也没关系,能这样说也挺好玩的。

最佳答案

函数 multimap 怎么样,它接受一组转换,并应用每个转换,将它们作为数组的数组返回:

// yay protocol extensions
extension SequenceType {
// looks like T->U works OK as a constraint
func multimap
<U, C: CollectionType
where C.Generator.Element == Generator.Element->U>
(transformations: C) -> [[U]] {
return transformations.map {
self.map($0)
}
}
}

然后像这样使用它:

let arr = ["hey", "ho"]

let double: String->String = { $0 + $0 }
let uppercase: String->String = { $0.uppercaseString }

arr.multimap([double, uppercase])
// returns [["heyhey", "hoho"], ["HEY", "HO"]]

或者它可能以可变形式非常好:

extension SequenceType {
func multimap<U>(transformations: (Generator.Element->U)...) -> [[U]] {
return self.multimap(transformations)
}
}

arr.multimap({ $0 + $0 }, { $0.uppercaseString })

编辑:如果你想要单独的变量,我认为你能做的最好的是一个destructure函数(不幸的是你必须为每个n元组声明n次):

// I don't think this can't be expressed as a protocol extension quite yet
func destructure<C: CollectionType>(source: C) -> (C.Generator.Element,C.Generator.Element) {
precondition(source.count == 2)
return (source[source.startIndex],source[source.startIndex.successor()])
}

// and, since it's a function, let's declare pipe forward
// to make it easier to call
infix operator |> { }
func |> <T,U>(lhs: T, rhs: T->U) -> U {
return rhs(lhs)
}

然后你可以像这样声明变量:

let (doubled,uppercased)
= arr.multimap({ $0 + $0 }, { $0.uppercaseString }) |> destructure

是的,这有点低效,因为您必须构建数组然后将其拆开——但这真的不会很重要,因为数组是写时复制的,而且我们谈论的是一小部分它们在外部数组中。

编辑:使用新的 guard 语句的借口:

func destructure<C: Sliceable where C.SubSlice.Generator.Element == C.Generator.Element>(source: C) -> (C.Generator.Element,C.Generator.Element) {
guard let one = source.first else { fatalError("empty source") }
guard let two = dropFirst(source).first else { fatalError("insufficient elements") }

return (one,two)
}

关于arrays - Swift 数组循环一次,写很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30761287/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com