【问题标题】:Does Swift have one-sided strides?斯威夫特有片面的进步吗?
【发布时间】:2020-08-01 07:54:34
【问题描述】:

我想做这样的事情:

let sequence1 = stride(from: Int32(2), by: 2)
for (i, address) in zip(sequence1, addresses) {
  sqlite3_bind_int64(stmt, i, address.userID)
  sqlite3_bind_int(stmt, i+1, address.deviceID)
}

但是stride(from:by:) 不存在。

我知道我可以将第一行改为:

let sequence1 = stride(from: Int32(2), through: Int32.max, by: 2)

或到:

let sequence1 = sequence(first: Int32(2), next: { $0 + 2 })

而且我知道 Swift 的范围是单向的,例如 PartialRangeFrom,但是 Swift 有单向的跨步吗?

相关:

【问题讨论】:

  • 您也可以使用for (i, address) in zip(1..., addresses),然后使用2*i2*i+1。 – 不,我不认为 Swift 有片面的进步。
  • let seq1 = (1...).lazy.map { $0 * 2 } 是另一种解决方法。
  • @MartinR 别介意我有他的最后一个问题zip(Int32(1)..., addresses)
  • 在这种特殊情况下,迭代次数也是已知的,所以let seq1 = stride(from: 2, to: 2 + 2 * addresses.count, by: 2) 也可以工作。
  • 太棒了!谢谢@MartinR,感谢您提供所有其他选项。 :-)

标签: swift range sequence


【解决方案1】:

不,在 Swift 中没有片面的进步。

对于一个一般的(惰性求值的)序列,每隔一个整数就迭代一次

let sequence1 = sequence(first: Int32(2), next: { $0 + 2 })

是一个简单、清晰、灵活的解决方案。另一种选择是

let sequence1 = (Int32(1)...).lazy.map { $0 * 2 }

在您的特定情况下,我会简单地使用单边范围:

for (i, address) in zip(Int32(1)..., addresses) {
    sqlite3_bind_int64(stmt, 2 * i, address.userID)
    sqlite3_bind_int(stmt, 2 * i + 1, address.deviceID)
}

【讨论】:

    【解决方案2】:

    就像他们说的,不。但无论如何你都不想要那样。加分太多了。打破你的部分范围! ⚒️

    public extension Sequence {
      /// Splits a `Sequence` into equal "chunks".
      /// - Parameter maxArrayCount: The maximum number of elements in a chunk.
      /// - Returns: `Array`s with `maxArrayCount` `counts`,
      ///   until the last chunk, which may be smaller.
      subscript(maxArrayCount maxCount: Int) -> AnySequence<[Element]> {
        .init(
          sequence( state: makeIterator() ) { iterator in
            Optional(
              (0..<maxCount).compactMap { _ in iterator.next() },
              nilWhen: \.isEmpty
            )
          }
        )
      }
    }
    
    public extension Optional {
      /// Wraps a value in an optional, based on a condition.
      /// - Parameters:
      ///   - wrapped: A non-optional value.
      ///   - getIsNil: The condition that will result in `nil`.
      init(
        _ wrapped: Wrapped,
        nilWhen getIsNil: (Wrapped) throws -> Bool
      ) rethrows {
        self = try getIsNil(wrapped) ? nil : wrapped
      }
    }
    
    zip( (2...)[maxArrayCount: 2], addresses ).forEach {
      sqlite3_bind_int64(stmt, $0[0], $1.userID)
      sqlite3_bind_int(stmt, $0[1], $1.deviceID)
    }
    

    【讨论】:

    • 使用zip((Int32(2)...)[maxArrayCount: 2], addresses).forEachdropbox.com/s/kw7lyza1u7wfqhh/Jessy%20pict%202.png?dl=1
    • 使用zip((2...)[maxArrayCount: 2], addresses).forEach {dropbox.com/s/ezn333byqomjnii/Jessy%20pict%201.jpg?dl=1
    • Jessy 和@LeoDabus:你们都是对的:使用func f(_ i32: Int32) { },以下编译:(2...)[maxArrayCount: 2].forEach { f($0[0]) },因为它是一个“单表达式闭包”,编译器会自动推断类型。但是(2...)[maxArrayCount: 2].forEach { f($0[0]) ; f($0[1]) } 无法编译。在这里您必须使用(Int32(2)...) 或在闭包中添加类型签名:(2...)[maxArrayCount: 2].forEach { (i: [Int32]) in f(i[0]) ; f(i[1]) }
    猜你喜欢
    • 2017-07-22
    • 2017-03-24
    • 1970-01-01
    • 2016-02-08
    • 2017-11-13
    • 2015-08-19
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多