美文网首页iOS Developer
Swift泛型应用:模型数组去重

Swift泛型应用:模型数组去重

作者: ReevesGoo | 来源:发表于2017-11-26 18:49 被阅读0次

我们在Swift开发过程中经常会碰到数组去重的情况,基本数据类型数组的去重比较好办,那如果碰到model模型类的数组去重,又怎么进行科学合理的处理呢?通常对model进行去重,要依赖其某个属性,一般是一个唯一ID,然后通过该ID来进行判断是否有重复的模型。
比如有个模型AModel如下:

class AModel {
    
    var name: String?
    var img: String?
    var aID: Int = 0 //唯一ID
 
}

普通处理

AModel的属性中有可以用来判断唯一性的aID,因此我们在对装着AModel类型的数组[AModel]进行去重时可以这么处理:

func handleFilterArray(arr:[AModel]) -> [AModel] {
        var temp = [AModel]()  //存放符合条件的model
        var idxArr = [Int]()   //存放符合条件model的aID,用来判断是否重复
        for model in arr {
            let index = model.aID   //遍历获得model的唯一标识aID
            if !idxArr.contains(index){    //如果该aID已经添加过,则不再添加
                idxArr.append(index)    
                temp.append(model)    //如果该aID没有添加过,则添加到temp数组中
            }
        }
        return temp    //最终返回的数组中已经筛选掉重复aID的model
    }

泛型处理

如果我们需要处理不同model类型的数组,那我们是否可以将上面的方法写成一个通用的方法,比如下面这样用Swift的泛型来处理:

//T为不同model的类型
func handleFilterArray(arr:[T]) -> [T] {
     //具体实现
}

可是我们碰到一个问题,你用泛型来写的话,这个泛型无法确定你不同模型中需要判断的那个ID是什么,因为BModel的唯一ID是bID,CModel的唯一ID是cID,因此我们怎么才能把这个不同的标识符给带到这个函数中来呢,下面先来看方法一,利用protocol来处理:

protocol arrayFilterable {
    var identifer:Int {get}  //该只读属性用来获取不同model的不同唯一ID
}

extension AModel: arrayFilterable{
    var identifer: Int{
        return aID  //AModel则返回aID
    }
}

extension BModel: arrayFilterable{
    var identifer: Int{
        return bID  //BModel则返回bID
    }
}

然后我们的处理方法就可以写成这样:

func handleFilterArray<T:arrayFilterable>(arr:[T]) -> [T] {
        var temp = [T]()
        var idxArr = [Int]()
        for model in arr {
            let index = model.identifer  //通过identifer来判断不同模型是否有重复数据
            if !idxArr.contains(index){
                idxArr.append(index)
                temp.append(model)
            }
        }
        return temp
    }

更合理的泛型处理

但以上的方法是不是还是显得有点不那么高效,毕竟需要每个模型都遵循arrayFilterable协议,而且显得可扩展性一般,如果有一个DModel用来判断唯一性的不是ID,而是一个字符串呢,我们再来看看方法二,利用泛型结合Swift数组的高阶函数map来处理:

//直接给Array扩展一个方法
extension Array {

  //该函数的参数filterCall是一个带返回值的闭包,传入模型T,返回一个E类型
   func handleFilter<E: Equatable>(_ filterCall: (T) -> E) -> [T] {
      var temp = [T]()
      for model in self {
          //调用filterCall,获得需要用来判断的属性E
          let identifer = filterCall(model)  
          //此处利用map函数 来将model类型数组转换成E类型的数组,以此来判断
          identifer 是否已经存在,如不存在则将model添加进temp
          if !temp.map( { filterCall($0) } ).contains(identifer) {
              temp.append(model)
          }
      }
      return temp
   }
}

上面传入闭包filterCall的返回值E,就是模型的属性中用来判断唯一型的那个属性,需要遵循Equatable,才能使用数组的contains函数来判断是否已经存在。

如果AModel用来判断唯一性的不是aID,而是name属性,则一个装着有好多重复AModel的数组AModelArray可以这么调用这个函数:

let filterArray = AModelArray.handleFilter( { $0.name } )

$0.name即filterCall闭包的返回值,用来判断数组中model唯一性的依据。

结语

通过这个小应用,可以看出Swift中强大的泛型特性能够让我们根据不同的需求,来编写灵活强大的函数和类型,让我们避免重复冗余的代码,更加快速高效的达到应用目的。

相关文章

  • Swift泛型应用:模型数组去重

    我们在Swift开发过程中经常会碰到数组去重的情况,基本数据类型数组的去重比较好办,那如果碰到model模型类的数...

  • Swift学习:泛型

    本篇将详细总结介绍Swift泛型的用法;Swift泛型代码让你能够根据自定义的需求,编写出适用于任意类型、灵活可重...

  • iOS学习笔记47-Swift(七)泛型

    一、Swift泛型介绍 泛型是为Swift编程灵活性的一种语法,在函数、枚举、结构体、类中都得到充分的应用,它的引...

  • Swift 中的泛型

    Swift泛型介绍 泛型是为Swift编程灵活性的一种语法,在函数、枚举、结构体、类中都得到充分的应用,它的引入可...

  • swift泛型

    一、swift泛型介绍 泛型是为swift编程灵活性的一种语法,在函数、枚举、结构体、类中都得到充分的应用,它的引...

  • Swift-泛型笔记

    Swift 泛型 Swift 提供了泛型让你写出灵活且可重用的函数和类型。 Swift 标准库是通过泛型代码构建出...

  • [ WWDC2018 ] - Swift 泛型 Swift Ge

    Swift 泛型历史 我们首先来回顾一下 Swift 中对于泛型支持的历史变更,看看现在在 Swift 中,泛型都...

  • Swift 运用协议泛型封装网络层

    Swift 运用协议泛型封装网络层 Swift 运用协议泛型封装网络层

  • 2021-12-01

    swift5基本语法-泛型函数和泛型类型 Swift中泛型可以将类型参数化,提高代码复用率,减少代码量。 一、泛型...

  • Swift 泛型简单应用

    泛型从字面来理解就是一种泛指的类型,通过在类、方法、接口等指定泛型的类型,可以避免重写,达到重用的目的,而且可以通...

网友评论

    本文标题:Swift泛型应用:模型数组去重

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