使用 Swift 中的索引进行映射或缩减
Map or reduce with index in Swift
有没有办法在map
或reduce
中获取数组的索引在Swift中?我正在 Ruby.
中寻找类似 each_with_index
的内容
func lunhCheck(number : String) -> Bool
{
var odd = true;
return reverse(number).map { String([=11=]).toInt()! }.reduce(0) {
odd = !odd
return [=11=] + (odd ? ( == 9 ? 9 : ( * 2) % 9) : )
} % 10 == 0
}
lunhCheck("49927398716")
lunhCheck("49927398717")
我想去掉 odd
变量 above。
您可以使用 enumerate
将序列(Array
、String
等)转换为具有整数计数器和元素配对的元组序列。即:
let numbers = [7, 8, 9, 10]
let indexAndNum: [String] = numbers.enumerate().map { (index, element) in
return "\(index): \(element)"
}
print(indexAndNum)
// ["0: 7", "1: 8", "2: 9", "3: 10"]
请注意,这与获取集合的 index 不同——enumerate
返回一个整数计数器。这与数组的索引相同,但在字符串或字典上用处不大。要获取每个元素的实际索引,您可以使用 zip
:
let actualIndexAndNum: [String] = zip(numbers.indices, numbers).map { "\([=11=]): \()" }
print(actualIndexAndNum)
// ["0: 7", "1: 8", "2: 9", "3: 10"]
当使用带有 reduce
的枚举序列时,您将无法在元组中分隔索引和元素,因为方法签名中已经有 accumulating/current 元组。相反,您需要在 reduce
闭包的第二个参数上使用 .0
和 .1
:
let summedProducts = numbers.enumerate().reduce(0) { (accumulate, current) in
return accumulate + current.0 * current.1
// ^ ^
// index element
}
print(summedProducts) // 56
Swift 3.0 及以上
因为 Swift 3.0 语法完全不同。
此外,您可以使用 short-syntax/inline 将数组映射到字典:
let numbers = [7, 8, 9, 10]
let array: [(Int, Int)] = numbers.enumerated().map { ([=13=], ) }
// ^ ^
// index element
产生:
[(0, 7), (1, 8), (2, 9), (3, 10)]
除了 Nate Cook 的 map
示例之外,您还可以将此行为应用于 reduce
。
let numbers = [1,2,3,4,5]
let indexedNumbers = reduce(numbers, [:]) { (memo, enumerated) -> [Int: Int] in
return memo[enumerated.index] = enumerated.element
}
// [0: 1, 1: 2, 2: 3, 3: 4, 4: 5]
请注意,作为 enumerated
传入闭包的 EnumerateSequence
不能以嵌套方式分解,因此元组的成员必须在闭包内分解(即 enumerated.index
).
对于Swift 2.1
我写了下一个函数:
extension Array {
public func mapWithIndex<T> (f: (Int, Element) -> T) -> [T] {
return zip((self.startIndex ..< self.endIndex), self).map(f)
}
}
然后像这样使用它:
let numbers = [7, 8, 9, 10]
let numbersWithIndex: [String] = numbers.mapWithIndex { (index, number) -> String in
return "\(index): \(number)"
}
print("Numbers: \(numbersWithIndex)")
这是 CollectionType 扩展 swift 2.1 使用抛出和重新抛出:
extension CollectionType {
func map<T>(@noescape transform: (Self.Index, Self.Generator.Element) throws -> T) rethrows -> [T] {
return try zip((self.startIndex ..< self.endIndex), self).map(transform)
}
}
我知道这不是您要问的,但可以解决您的问题。您可以在不扩展任何内容的情况下尝试此 swift 2.0 Luhn 方法:
func luhn(string: String) -> Bool {
var sum = 0
for (idx, value) in string.characters.reverse().map( { Int(String([=11=]))! }).enumerate() {
sum += ((idx % 2 == 1) ? (value == 9 ? 9 : (value * 2) % 9) : value)
}
return sum > 0 ? sum % 10 == 0 : false
}
使用 Swift 3,当你有一个符合 Sequence
协议的对象并且你想要 link 它里面的每个元素及其索引时,你可以使用 enumerated()
方法。
例如:
let array = [1, 18, 32, 7]
let enumerateSequence = array.enumerated() // type: EnumerateSequence<[Int]>
let newArray = Array(enumerateSequence)
print(newArray) // prints: [(0, 1), (1, 18), (2, 32), (3, 7)]
let reverseRandomAccessCollection = [1, 18, 32, 7].reversed()
let enumerateSequence = reverseRandomAccessCollection.enumerated() // type: EnumerateSequence<ReverseRandomAccessCollection<[Int]>>
let newArray = Array(enumerateSequence)
print(newArray) // prints: [(0, 7), (1, 32), (2, 18), (3, 1)]
let reverseCollection = "8763".characters.reversed()
let enumerateSequence = reverseCollection.enumerated() // type: EnumerateSequence<ReverseCollection<String.CharacterView>>
let newArray = enumerateSequence.map { ([=12=].0 + 1, String([=12=].1) + "A") }
print(newArray) // prints: [(1, "3A"), (2, "6A"), (3, "7A"), (4, "8A")]
因此,在最简单的情况下,您可以像这样在 Playground 中实现 Luhn 算法:
let array = [8, 7, 6, 3]
let reversedArray = array.reversed()
let enumerateSequence = reversedArray.enumerated()
let luhnClosure = { (sum: Int, tuple: (index: Int, value: Int)) -> Int in
let indexIsOdd = tuple.index % 2 == 1
guard indexIsOdd else { return sum + tuple.value }
let newValue = tuple.value == 9 ? 9 : tuple.value * 2 % 9
return sum + newValue
}
let sum = enumerateSequence.reduce(0, luhnClosure)
let bool = sum % 10 == 0
print(bool) // prints: true
如果你从String
开始,你可以这样实现:
let characterView = "8763".characters
let mappedArray = characterView.flatMap { Int(String([=14=])) }
let reversedArray = mappedArray.reversed()
let enumerateSequence = reversedArray.enumerated()
let luhnClosure = { (sum: Int, tuple: (index: Int, value: Int)) -> Int in
let indexIsOdd = tuple.index % 2 == 1
guard indexIsOdd else { return sum + tuple.value }
let newValue = tuple.value == 9 ? 9 : tuple.value * 2 % 9
return sum + newValue
}
let sum = enumerateSequence.reduce(0, luhnClosure)
let bool = sum % 10 == 0
print(bool) // prints: true
如果您需要重复这些操作,您可以将代码重构为扩展:
extension String {
func luhnCheck() -> Bool {
let characterView = self.characters
let mappedArray = characterView.flatMap { Int(String([=15=])) }
let reversedArray = mappedArray.reversed()
let enumerateSequence = reversedArray.enumerated()
let luhnClosure = { (sum: Int, tuple: (index: Int, value: Int)) -> Int in
let indexIsOdd = tuple.index % 2 == 1
guard indexIsOdd else { return sum + tuple.value }
let newValue = tuple.value == 9 ? 9 : tuple.value * 2 % 9
return sum + newValue
}
let sum = enumerateSequence.reduce(0, luhnClosure)
return sum % 10 == 0
}
}
let string = "8763"
let luhnBool = string.luhnCheck()
print(luhnBool) // prints: true
或者,更简洁的方式:
extension String {
func luhnCheck() -> Bool {
let sum = characters
.flatMap { Int(String([=16=])) }
.reversed()
.enumerated()
.reduce(0) {
let indexIsOdd = .0 % 2 == 1
guard indexIsOdd else { return [=16=] + .1 }
return [=16=] + (.1 == 9 ? 9 : .1 * 2 % 9)
}
return sum % 10 == 0
}
}
let string = "8763"
let luhnBool = string.luhnCheck()
print(luhnBool) // prints: true
减少 swift :
let numbers = [7,3,10]
let sum = numbers.reduce(0) {
[=10=] +
}
print(sum) // 20
映射在swift:
将模型转换为我们需要的模型
我们希望将名称数组更改为大写字母的名称数组,
意味着我想要的一切
let names = ["John", "Paul", "George", "Ringo"]
let uppercased = names.map {
[=11=].uppercased()
}
print(uppercased) // ["JOHN", "PAUL", "GEORGE", "RINGO"]
希望你明白我的意思:)。
有没有办法在map
或reduce
中获取数组的索引在Swift中?我正在 Ruby.
each_with_index
的内容
func lunhCheck(number : String) -> Bool
{
var odd = true;
return reverse(number).map { String([=11=]).toInt()! }.reduce(0) {
odd = !odd
return [=11=] + (odd ? ( == 9 ? 9 : ( * 2) % 9) : )
} % 10 == 0
}
lunhCheck("49927398716")
lunhCheck("49927398717")
我想去掉 odd
变量 above。
您可以使用 enumerate
将序列(Array
、String
等)转换为具有整数计数器和元素配对的元组序列。即:
let numbers = [7, 8, 9, 10]
let indexAndNum: [String] = numbers.enumerate().map { (index, element) in
return "\(index): \(element)"
}
print(indexAndNum)
// ["0: 7", "1: 8", "2: 9", "3: 10"]
请注意,这与获取集合的 index 不同——enumerate
返回一个整数计数器。这与数组的索引相同,但在字符串或字典上用处不大。要获取每个元素的实际索引,您可以使用 zip
:
let actualIndexAndNum: [String] = zip(numbers.indices, numbers).map { "\([=11=]): \()" }
print(actualIndexAndNum)
// ["0: 7", "1: 8", "2: 9", "3: 10"]
当使用带有 reduce
的枚举序列时,您将无法在元组中分隔索引和元素,因为方法签名中已经有 accumulating/current 元组。相反,您需要在 reduce
闭包的第二个参数上使用 .0
和 .1
:
let summedProducts = numbers.enumerate().reduce(0) { (accumulate, current) in
return accumulate + current.0 * current.1
// ^ ^
// index element
}
print(summedProducts) // 56
Swift 3.0 及以上
因为 Swift 3.0 语法完全不同。
此外,您可以使用 short-syntax/inline 将数组映射到字典:
let numbers = [7, 8, 9, 10]
let array: [(Int, Int)] = numbers.enumerated().map { ([=13=], ) }
// ^ ^
// index element
产生:
[(0, 7), (1, 8), (2, 9), (3, 10)]
除了 Nate Cook 的 map
示例之外,您还可以将此行为应用于 reduce
。
let numbers = [1,2,3,4,5]
let indexedNumbers = reduce(numbers, [:]) { (memo, enumerated) -> [Int: Int] in
return memo[enumerated.index] = enumerated.element
}
// [0: 1, 1: 2, 2: 3, 3: 4, 4: 5]
请注意,作为 enumerated
传入闭包的 EnumerateSequence
不能以嵌套方式分解,因此元组的成员必须在闭包内分解(即 enumerated.index
).
对于Swift 2.1
我写了下一个函数:
extension Array {
public func mapWithIndex<T> (f: (Int, Element) -> T) -> [T] {
return zip((self.startIndex ..< self.endIndex), self).map(f)
}
}
然后像这样使用它:
let numbers = [7, 8, 9, 10]
let numbersWithIndex: [String] = numbers.mapWithIndex { (index, number) -> String in
return "\(index): \(number)"
}
print("Numbers: \(numbersWithIndex)")
这是 CollectionType 扩展 swift 2.1 使用抛出和重新抛出:
extension CollectionType {
func map<T>(@noescape transform: (Self.Index, Self.Generator.Element) throws -> T) rethrows -> [T] {
return try zip((self.startIndex ..< self.endIndex), self).map(transform)
}
}
我知道这不是您要问的,但可以解决您的问题。您可以在不扩展任何内容的情况下尝试此 swift 2.0 Luhn 方法:
func luhn(string: String) -> Bool {
var sum = 0
for (idx, value) in string.characters.reverse().map( { Int(String([=11=]))! }).enumerate() {
sum += ((idx % 2 == 1) ? (value == 9 ? 9 : (value * 2) % 9) : value)
}
return sum > 0 ? sum % 10 == 0 : false
}
使用 Swift 3,当你有一个符合 Sequence
协议的对象并且你想要 link 它里面的每个元素及其索引时,你可以使用 enumerated()
方法。
例如:
let array = [1, 18, 32, 7]
let enumerateSequence = array.enumerated() // type: EnumerateSequence<[Int]>
let newArray = Array(enumerateSequence)
print(newArray) // prints: [(0, 1), (1, 18), (2, 32), (3, 7)]
let reverseRandomAccessCollection = [1, 18, 32, 7].reversed()
let enumerateSequence = reverseRandomAccessCollection.enumerated() // type: EnumerateSequence<ReverseRandomAccessCollection<[Int]>>
let newArray = Array(enumerateSequence)
print(newArray) // prints: [(0, 7), (1, 32), (2, 18), (3, 1)]
let reverseCollection = "8763".characters.reversed()
let enumerateSequence = reverseCollection.enumerated() // type: EnumerateSequence<ReverseCollection<String.CharacterView>>
let newArray = enumerateSequence.map { ([=12=].0 + 1, String([=12=].1) + "A") }
print(newArray) // prints: [(1, "3A"), (2, "6A"), (3, "7A"), (4, "8A")]
因此,在最简单的情况下,您可以像这样在 Playground 中实现 Luhn 算法:
let array = [8, 7, 6, 3]
let reversedArray = array.reversed()
let enumerateSequence = reversedArray.enumerated()
let luhnClosure = { (sum: Int, tuple: (index: Int, value: Int)) -> Int in
let indexIsOdd = tuple.index % 2 == 1
guard indexIsOdd else { return sum + tuple.value }
let newValue = tuple.value == 9 ? 9 : tuple.value * 2 % 9
return sum + newValue
}
let sum = enumerateSequence.reduce(0, luhnClosure)
let bool = sum % 10 == 0
print(bool) // prints: true
如果你从String
开始,你可以这样实现:
let characterView = "8763".characters
let mappedArray = characterView.flatMap { Int(String([=14=])) }
let reversedArray = mappedArray.reversed()
let enumerateSequence = reversedArray.enumerated()
let luhnClosure = { (sum: Int, tuple: (index: Int, value: Int)) -> Int in
let indexIsOdd = tuple.index % 2 == 1
guard indexIsOdd else { return sum + tuple.value }
let newValue = tuple.value == 9 ? 9 : tuple.value * 2 % 9
return sum + newValue
}
let sum = enumerateSequence.reduce(0, luhnClosure)
let bool = sum % 10 == 0
print(bool) // prints: true
如果您需要重复这些操作,您可以将代码重构为扩展:
extension String {
func luhnCheck() -> Bool {
let characterView = self.characters
let mappedArray = characterView.flatMap { Int(String([=15=])) }
let reversedArray = mappedArray.reversed()
let enumerateSequence = reversedArray.enumerated()
let luhnClosure = { (sum: Int, tuple: (index: Int, value: Int)) -> Int in
let indexIsOdd = tuple.index % 2 == 1
guard indexIsOdd else { return sum + tuple.value }
let newValue = tuple.value == 9 ? 9 : tuple.value * 2 % 9
return sum + newValue
}
let sum = enumerateSequence.reduce(0, luhnClosure)
return sum % 10 == 0
}
}
let string = "8763"
let luhnBool = string.luhnCheck()
print(luhnBool) // prints: true
或者,更简洁的方式:
extension String {
func luhnCheck() -> Bool {
let sum = characters
.flatMap { Int(String([=16=])) }
.reversed()
.enumerated()
.reduce(0) {
let indexIsOdd = .0 % 2 == 1
guard indexIsOdd else { return [=16=] + .1 }
return [=16=] + (.1 == 9 ? 9 : .1 * 2 % 9)
}
return sum % 10 == 0
}
}
let string = "8763"
let luhnBool = string.luhnCheck()
print(luhnBool) // prints: true
减少 swift :
let numbers = [7,3,10]
let sum = numbers.reduce(0) {
[=10=] +
}
print(sum) // 20
映射在swift:
将模型转换为我们需要的模型
我们希望将名称数组更改为大写字母的名称数组,
意味着我想要的一切
let names = ["John", "Paul", "George", "Ringo"]
let uppercased = names.map {
[=11=].uppercased()
}
print(uppercased) // ["JOHN", "PAUL", "GEORGE", "RINGO"]
希望你明白我的意思:)。