Int 类型不符合协议序列

Posted

技术标签:

【中文标题】Int 类型不符合协议序列【英文标题】:Type Int does not conform to protocol sequence 【发布时间】:2017-06-22 20:17:26 【问题描述】:

我在 Swift 3 中有以下代码:

var numbers = [1,2,1]
for number in numbers.count - 1  // error
    if numbers[number]  < numbers[number + 1] 
        print(number)
    

我正在检查索引 [number] 上的值是否总是高于索引 [number + 1] 上的值。我收到一个错误:

Int 类型不符合协议顺序

有什么想法吗?

【问题讨论】:

numbers.count - 1 不是一个序列,它是一个整数。所以不能迭代。你需要像for number in numbers 这样的东西。顺便说一句,这是什么语言? Swift 3,我知道这行不通,但我需要一个命令,它将这个代码循环为 numbers.count - 1 次。 for index in numbers.indices BTW 在尝试访问数组中的下一个元素之前,您需要检查实际索引 if index + 1 &lt; numbers.count 之后是否还有另一个元素 【参考方案1】:

可能很快。 您可以使用此迭代。

for number in 0..<(numbers.count-1)

【讨论】:

【参考方案2】:

错误是因为Int 不是Sequence。您可以按照已经建议的方式创建一个范围,该范围确实符合一个序列并允许使用 for in 进行迭代。

使Int符合序列的一种方法是:

extension Int: Sequence 
    public func makeIterator() -> CountableRange<Int>.Iterator 
        return (0..<self).makeIterator()
    

这将允许将其用作带有for in 的序列。

for i in 5 
    print(i)

但我不建议这样做。这只是为了展示协议的强大功能,但在实际代码库中可能会造成混淆。

从您的示例来看,您似乎正在尝试比较集合的连续元素。自定义迭代器可以做到这一点,同时保持代码的可读性:

public struct ConsecutiveSequence<T: IteratorProtocol>: IteratorProtocol, Sequence 
    private var base: T
    private var index: Int
    private var previous: T.Element?

    init(_ base: T) 
        self.base = base
        self.index = 0
    

    public typealias Element = (T.Element, T.Element)

    public mutating func next() -> Element? 
        guard let first = previous ?? base.next(), let second = base.next() else 
            return nil
        

        previous = second

        return (first, second)
    


extension Sequence 
    public func makeConsecutiveIterator() -> ConsecutiveSequence<Self.Iterator> 
        return ConsecutiveSequence(self.makeIterator())
    

可以用作:

for (x, y) in [1,2,3,4].makeConsecutiveIterator() 
    if (x < y) 
        print(x)
    

在上面的示例中,迭代器将遍历以下对:

(1, 2)
(2, 3)
(3, 4)

【讨论】:

【参考方案3】:

这可能有点晚了,但你可以这样做:

for number in numbers  

代替:

for number in numbers.count - 1  

要使 for 循环工作,需要一个序列(范围)。一个序列由一个声明值、一个结束值以及介于两者之间的所有内容组成。这意味着可以告诉 for 循环使用以太循环遍历一个范围

for number in 0...numbers.count-1     `or`   for number in numbers   

两个例子都给出了 nesasery 序列。其中:

 for number in numbers.count - 1  

只给出一个可能是开始值或结束值的值,因此无法计算出 for 循环必须运行多少次。

欲了解更多信息,请参阅Apple's swift control flow documnetation

【讨论】:

【参考方案4】:

如果您尝试枚举数组而不是枚举数组,也会出现此错误。例如:

for (index, element) in [0, 3, 4]  


应该是:

for (index, element) in [0, 3, 4].enumerated()  


【讨论】:

【参考方案5】:

所以首先你需要了解什么是序列.. 一种提供对其元素的顺序、迭代访问的类型。

序列是一个值列表,您可以一次遍历一个值。遍历序列元素的最常见方法是使用 for-in 循环:

让 oneTwoThree = 1...3。 // 序列

for循环其实是指

对于序列中的数字

所以你需要使用 对于 0 中的数字..

【讨论】:

【参考方案6】:

错误是因为 number 不是索引,而是每次迭代时数组的元素。你可以像这样修改你的代码:

var numbers = [1,2,1,0,3]
for number in 0..<numbers.count - 1 
    if numbers[number] < numbers[number + 1] 
        print(numbers[number])
    

或者有一个使用 sort 方法的技巧,但这是一种 hack(是的,子索引是正确的,但看起来像倒置的;你可以直接在 Playground 上尝试这个):

var numbers = [1,2,1,0,3]
numbers.sort 
    if $0.1 < $0.0 
        print ($0.1)
    
    return false

【讨论】:

【参考方案7】:

对我来说,这个错误发生在我尝试编写 for 循环时,不是针对数组而是针对数组的单个元素。

例如:

let array = [1,2,3,4]
let item = array[0]

for its in item

   print(its)

这会产生一个错误,例如:Type Int does not conform to protocol 'sequence'

所以,如果你在for循环中遇到这个错误,请检查你是否在循环数组。

【讨论】:

以上是关于Int 类型不符合协议序列的主要内容,如果未能解决你的问题,请参考以下文章

泛型类型在不透明类型的帮助下符合序列:一些 IteratorProtocol

Fluent Python: Slice

名为“名称”的操作不符合所需的签名。参数类型必须是实体类型或预定义的可序列化类型之一

iOS 自动实现对象序列化方法

Python 基本数据类型和序列类型

尝试符合可等式泛型 Set 时,类型“任何”不符合协议“等式”