Swift泛型應用:模型數(shù)組去重

我們在Swift開發(fā)過程中經(jīng)常會碰到數(shù)組去重的情況,基本數(shù)據(jù)類型數(shù)組的去重比較好辦,那如果碰到model模型類的數(shù)組去重,又怎么進行科學合理的處理呢?通常對model進行去重,要依賴其某個屬性,一般是一個唯一ID,然后通過該ID來進行判斷是否有重復的模型。
比如有個模型AModel如下:

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

普通處理

AModel的屬性中有可以用來判斷唯一性的aID,因此我們在對裝著AModel類型的數(shù)組[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已經(jīng)添加過,則不再添加
                idxArr.append(index)    
                temp.append(model)    //如果該aID沒有添加過,則添加到temp數(shù)組中
            }
        }
        return temp    //最終返回的數(shù)組中已經(jīng)篩選掉重復aID的model
    }

泛型處理

如果我們需要處理不同model類型的數(shù)組,那我們是否可以將上面的方法寫成一個通用的方法,比如下面這樣用Swift的泛型來處理:

//T為不同model的類型
func handleFilterArray(arr:[T]) -> [T] {
     //具體實現(xiàn)
}

可是我們碰到一個問題,你用泛型來寫的話,這個泛型無法確定你不同模型中需要判斷的那個ID是什么,因為BModel的唯一ID是bID,CModel的唯一ID是cID,因此我們怎么才能把這個不同的標識符給帶到這個函數(shù)中來呢,下面先來看方法一,利用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來判斷不同模型是否有重復數(shù)據(jù)
            if !idxArr.contains(index){
                idxArr.append(index)
                temp.append(model)
            }
        }
        return temp
    }

更合理的泛型處理

但以上的方法是不是還是顯得有點不那么高效,畢竟需要每個模型都遵循arrayFilterable協(xié)議,而且顯得可擴展性一般,如果有一個DModel用來判斷唯一性的不是ID,而是一個字符串呢,我們再來看看方法二,利用泛型結(jié)合Swift數(shù)組的高階函數(shù)map來處理:

//直接給Array擴展一個方法
extension Array {

  //該函數(shù)的參數(shù)filterCall是一個帶返回值的閉包,傳入模型T,返回一個E類型
   func handleFilter<E: Equatable>(_ filterCall: (T) -> E) -> [T] {
      var temp = [T]()
      for model in self {
          //調(diào)用filterCall,獲得需要用來判斷的屬性E
          let identifer = filterCall(model)  
          //此處利用map函數(shù) 來將model類型數(shù)組轉(zhuǎn)換成E類型的數(shù)組,以此來判斷
          identifer 是否已經(jīng)存在,如不存在則將model添加進temp
          if !temp.map( { filterCall($0) } ).contains(identifer) {
              temp.append(model)
          }
      }
      return temp
   }
}

上面?zhèn)魅腴]包filterCall的返回值E,就是模型的屬性中用來判斷唯一型的那個屬性,需要遵循Equatable,才能使用數(shù)組的contains函數(shù)來判斷是否已經(jīng)存在。

如果AModel用來判斷唯一性的不是aID,而是name屬性,則一個裝著有好多重復AModel的數(shù)組AModelArray可以這么調(diào)用這個函數(shù):

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

$0.name即filterCall閉包的返回值,用來判斷數(shù)組中model唯一性的依據(jù)。

結(jié)語

通過這個小應用,可以看出Swift中強大的泛型特性能夠讓我們根據(jù)不同的需求,來編寫靈活強大的函數(shù)和類型,讓我們避免重復冗余的代碼,更加快速高效的達到應用目的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容