ClosedRange<Int>.Index to Int in Swift?

huangapple go评论75阅读模式
英文:

ClosedRange<Int>.Index to Int in Swift?

问题

我的代码:

let range = 30...200 //范围可能有不同的边界
let index = range.firstIndex(of: 55)


问题是 `index` 具有类型 `ClosedRange&lt;Int&gt;.Index`,目前不清楚如何将其转换为 `Int` 以供进一步使用。

我理解将范围转换为数组并在其中查找整数索引可能更简单,但某种程度上应该允许单独使用 `ClosedRange&lt;Int&gt;.Index`。

注意:可能有类似的问题,但它们都是关于如何将 `ClosedRange&lt;Int&gt;` 转换为数组,而不是索引转换。
英文:

My code:

let range = 30...200 //ranges may have different bounds
let index = range.firstIndex(of: 55)

The problem is index has type ClosedRange&lt;Int&gt;.Index and it is unclear how to convert it to Int now for further usage.

I understand that it is simplier to convert range to array and look for int index in it but they somehow should allow to use ClosedRange&lt;Int&gt;.Index by itself

Note: there are may be similar questions but all of them about how to convert ClosedRange&lt;Int&gt; to an array, not index conversion

答案1

得分: 3

ClosedRange&lt;Bound&gt;.Index 只是一个枚举,它并没有提供有用的信息。

enum Index {
    case inRange(Bound)
    case pastEnd
}

只需像这样简单地实现这个枚举,就足以正确实现 Collection 和其他协议需要的与索引相关的方法。

如果 55 在范围内,firstIndex(of: 55) 将返回 inRange(55),否则返回 pastEnd

还要注意,只有当 Bound 遵循 Stridable 并且 Stride 遵循 SignedInteger 时,firstIndex以及其他 Collection 方法)才可用。毕竟,将 ClosedRange&lt;Double&gt;ClosedRange&lt;String&gt; 视为 Collection 是没有意义的。

因此,唯一适用于类似 firstIndex(of: 55) 操作的范围是 Bound: Stridable, Bound.Stride: SignedInteger。您可以使用 distance(to: lowerBound) 方法来查找在这种范围内元素的“数值”索引,该方法是 Stridable 上的一个方法。

extension ClosedRange where Bound: Strideable, Bound.Stride: SignedInteger {
    func numericIndex(of element: Bound) -> Bound.Stride? {
        if contains(element) {
            return element.distance(to: lowerBound)
        } else {
            return nil
        }
    }
}

对于 ClosedRange&lt;Int&gt;,这基本上是减法。在 30...200 中,55 的索引就是 55 - 30 = 25。

英文:

ClosedRange&lt;Bound&gt;.Index is literally just an enum that doesn't tell you anything useful.

enum Index {
    case inRange(Bound)
    case pastEnd
}

Something as simple as this is enough to correctly implement the index-related methods that Collection and other protocols require.

firstIndex(of: 55) would return inRange(55) if 55 is in the range, and pastEnd otherwise.

Also note that firstIndex (and other Collection methods) is only available when Bound conforms to Stridable and the Stride conforms to SignedInteger. After all, it doesn't make sense to treat a ClosedRange&lt;Double&gt; or a ClosedRange&lt;String&gt; as a Collection.

So the only ranges where an operation like firstIndex(of: 55) makes sense, is when Bound: Stridable, Bound.Stride: SignedInteger. You can find out the "numeric" index of an element in such a range by using distance(to: lowerBound), which is a method on Stridable.

extension ClosedRange where Bound: Strideable, Bound.Stride: SignedInteger {
    func numericIndex(of element: Bound) -&gt; Bound.Stride? {
        if contains(element) {
            return element.distance(to: lowerBound)
        } else {
            return nil
        }
    }
}

For ClosedRange&lt;Int&gt;, this is basically subtraction. The index of 55 in 30...200 is simply 55 - 30 = 25.

huangapple
  • 本文由 发表于 2023年7月24日 17:36:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76753159.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定