英文:
ClosedRange<Int>.Index to Int in Swift?
问题
我的代码:
let range = 30...200 //范围可能有不同的边界
let index = range.firstIndex(of: 55)
问题是 `index` 具有类型 `ClosedRange<Int>.Index`,目前不清楚如何将其转换为 `Int` 以供进一步使用。
我理解将范围转换为数组并在其中查找整数索引可能更简单,但某种程度上应该允许单独使用 `ClosedRange<Int>.Index`。
注意:可能有类似的问题,但它们都是关于如何将 `ClosedRange<Int>` 转换为数组,而不是索引转换。
英文:
My code:
let range = 30...200 //ranges may have different bounds
let index = range.firstIndex(of: 55)
The problem is index
has type ClosedRange<Int>.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<Int>.Index
by itself
Note: there are may be similar questions but all of them about how to convert ClosedRange<Int>
to an array, not index conversion
答案1
得分: 3
ClosedRange<Bound>.Index
只是一个枚举,它并没有提供有用的信息。
enum Index {
case inRange(Bound)
case pastEnd
}
只需像这样简单地实现这个枚举,就足以正确实现 Collection
和其他协议需要的与索引相关的方法。
如果 55 在范围内,firstIndex(of: 55)
将返回 inRange(55)
,否则返回 pastEnd
。
还要注意,只有当 Bound
遵循 Stridable
并且 Stride
遵循 SignedInteger
时,firstIndex
(以及其他 Collection
方法)才可用。毕竟,将 ClosedRange<Double>
或 ClosedRange<String>
视为 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<Int>
,这基本上是减法。在 30...200 中,55 的索引就是 55 - 30 = 25。
英文:
ClosedRange<Bound>.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<Double>
or a ClosedRange<String>
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) -> Bound.Stride? {
if contains(element) {
return element.distance(to: lowerBound)
} else {
return nil
}
}
}
For ClosedRange<Int>
, this is basically subtraction. The index of 55 in 30...200 is simply 55 - 30 = 25.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论