美文网首页swift-only 八条精选iOS Developer程序员
集合泛型处理时处理subsequence的技巧

集合泛型处理时处理subsequence的技巧

作者: 八条8tiao | 来源:发表于2016-07-28 10:16 被阅读70次

我们这几天一直在探究集合在泛型化时所遇到的问题。在另外一个内容集合索引与泛型中,我们讨论的是在集合泛型化处理的时候如何处理集合索引indices.这一次我们来看一下如何处理subsequence的问题。我们首先看一个需求。

在一个 集合中定位另一个集合元素第一次出现的位置

我们熟悉indexOf方法,用来定位一个集合元素第一次出现的位置,我们现在的需求是给集合类型做一个扩展,增加一个方法用来定位一个subsequence第一次在集合中出现的位置,例如:"or"第一次在“Hello,world"中出现的位置。

思考一下,问题好像并不难解决,只要集合中的元素可以进行比较相等就可以了,也就是说准守Equatable协议就可以了,所以我们尝试着写出下面这个代码片段。

extension CollectionType where Generator.Element: Equatable {
    func searchRange<Other: SequenceType where
        Other.Generator.Element == Generator.Element>(pattern: Other) -> Index? {
        
        for idx in self.indices {
            if suffixFrom(idx).startsWith(pattern) {
                return idx
            }
        }
        return nil
    }
}

这个时候我们会收到编译器提示的错误,抱怨我们的startsWith方法没有提供参数 isEquivalent ,我们经过翻看SequenceType的定义,我们会发现,实际上存在两个startsWith方法分别是:

  • startsWith(other: OtherSequence)
  • startsWith(other: OtherSequence,isEquivalent: {})

这也就是表明,我们的调用并没有什么不对,其实在这个时候就算我们迁就一下编译器,将方法调用改成

if suffixFrom(idx).startsWith(pattern,isEquivalent: {_,_ in true}) {
    return idx
}

即使这样,编译器也不会放过你的,它会继续提示你 OtherSequence 的类型无法推断。

问题的真正原因

** 其实问题的根本原因是出在了,我们虽然在泛型方法中通过约束条件Other.Generator.Element == Generator.Element,约束了两个集合的元素类型相同,但suffixFrom(idx)方法返回的是一个subsequence,这个subsequence的类型和Self的类型可不一定相同,而我们现在是用subsequence与Other类型进行对比,因此,方法中的泛型约束已经失效了。**

要解决这个问题我们可以这样做,增加一个泛型约束,另subsequence == Self.....

extension CollectionType where Generator.Element: Equatable,
    SubSequence == Self{
    func searchRange<Other: SequenceType where
        Other.Generator.Element == Generator.Element>(pattern: Other) -> Index? {
        
        for idx in self.indices {
        if suffixFrom(idx).startsWith(pattern) {
                return idx
            }
        }
        return nil
    }
}

通过 SubSequence == Self ,我们保证了Other.Generator.Element == Generator.Element>约束的有效。我们现在可以这样使用searchRange方法了

"Hello,world".characters.searchRange("or".characters)  // 7

进一步扩大适用范围

searchRange 虽然可以工作了,但是它只能用于像String这种,subsquence与self类型相等的情况,而对于数组之类的集合,subsquence与self一定是不相等的,那应该怎么办呢?sequence
其实我们并不是真的需要两个sequence类型相同,我们需要的只是集合内的元素类型相同就可以了。我们再调整一下代码。

extension CollectionType where Generator.Element: Equatable,
    SubSequence.Generator.Element == Generator.Element{
    func searchRange<Other: SequenceType where
        Other.Generator.Element == Generator.Element>(pattern: Other) -> Index? {
        
        for idx in self.indices {
        if suffixFrom(idx).startsWith(pattern) {
                return idx
            }
        }
        return nil
    }
}

通过 SubSequence.Generator.Element == Generator.Element 约束条件,我们把searchRange的方法扩大到了所有subsequence的元素与self中的元素类型相同的集合类型了。

总结

八条8tiao没有总结。

相关文章

  • 集合泛型处理时处理subsequence的技巧

    我们这几天一直在探究集合在泛型化时所遇到的问题。在另外一个内容集合索引与泛型中,我们讨论的是在集合泛型化处理的时候...

  • 泛型(jdk5.0新特性)

    在集合中使用泛型 1、集合接口或集合类在jdk5.0时都修改为带泛型的结构2、在实例化集合类时,可以指明具体的泛型...

  • Java 学习路线

    JavaSE 基础语法 面向对象 异常处理 常用类(包装类、String) 集合框架及泛型 IO 流 多线程 网络...

  • java学习第六天

    异常处理 异常处理机制 java提供的异常类一般是够用了,只有特殊的情况可能需要自己编写异常类 集合 泛型 当我们...

  • 泛型

    泛型的使用 jdk 5.0新增的特性 在集合中使用泛型 ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。...

  • Error处理,泛型

    swift系列课程 自定义错误 do-catch 处理Error 处理rethrows 处理defer 泛型 关联...

  • JavaSE学习笔记——泛型

    泛型在集合中的使用集合中不使用泛型时: public void test1(){ //1.在集合中没有使用...

  • spring 泛型处理

    java 泛型基础 泛型类型:泛型类型是在类型上参数化的泛型类或接口 泛型使用场景编译时前类型检查。定义为 Col...

  • C#基础提升系列——C#集合

    C#集合 有两种主要的集合类型:泛型集合和非泛型集合。 泛型集合被添加在 .NET Framework 2.0 中...

  • Java基础之泛型

    泛型 体验泛型 没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一...

网友评论

    本文标题:集合泛型处理时处理subsequence的技巧

    本文链接:https://www.haomeiwen.com/subject/jvlajttx.html