2017-09-05 120 views
0

我有這樣在字典數組中獲取重複值。斯威夫特

[ 
    ["itm_id": 4, "itm_name": Chicken], 
    ["itm_id": 4, "itm_name": Chicken], 
    ["itm_id": 4, "itm_name": Chicken], 
    ["itm_id": 7, "itm_name": Cat] 
] 

陣列我有這個數組字典,我通過在字典中的值,試圖將它們分組。所以在我上面的例子,我想知道創建一個字典,知道有多少字典有重複鍵:

[["item_id" : 4, count: 3], ["item_id" : 7, count: 1]]

itm_id: 4重複3次,計數爲3 itm_id: 7重複一次。

我怎樣才能做到這一點

+2

爲你的字典定義「平等」。你只需要'itm_id'匹配,或者'itm_id'和'itm_name'匹配?如果我有'[「itm_id」:4,「itm_name」:Duck]'?它等於'雞肉'嗎?如果你有不同的「雞」呢? –

+0

我建議使用結構而不是字典(如已經回答),使其符合'Hashable'協議,並使用'NSCountedSet'來知道對象在給定集合中重複的次數。 – EmilioPelaez

回答

1

我建議你創建的項目數組,而不是字典的struct這樣

struct Item{ 
    var itemID : Int 
    var name : String 

    init(dictionary:[String:Any]) { 
     itemID = dictionary["itm_id"] as? Int ?? 0 
     name = dictionary["itm_name"] as? String ?? "" 
    } 
} 

一旦你有Items陣列可以映射的元素特定項目ID作爲數組來獲取計數並將其從數組中移除。看看下面的代碼。不是最乾淨的實現,但它會幫助你解決問題。

func countDuplicates(){ 
    let dictionary = [["itm_id": 4, "itm_name": "Chicken"],["itm_id": 4, "itm_name": "Chicken"],["itm_id": 4, "itm_name": "Chicken"],["itm_id": 7, "itm_name": "Cat"]] 
    var items = [Item]() 
    var countArray = [[String:Any]]() 
    dictionary.forEach{ 
     items.append(Item(dictionary: $0)) 
    } 
    while items.count > 0 { 
     if let firstItem = items.first{ 
      let duplicateItems = items.filter{$0.itemID == firstItem.itemID} 
      var countDictionary = [String:Any]() 
      countDictionary["itm_id"] = firstItem.itemID 
      countDictionary["count"] = duplicateItems.count 
      countArray.append(countDictionary) 
      items = items.filter{$0.itemID != firstItem.itemID} 
     } 
    } 
    print(countArray) 
} 

這將打印[["itm_id": 4, "count": 3], ["itm_id": 7, "count": 1]]

我假定ChickenCat都是字符串。如果他們不是一個字符串,但一個類類型你可以重寫Item結構來這樣的事情

class Animal{} 

class Chicken:Animal{} 

class Cat:Animal{} 

struct Item<T:Animal>{ 
    var itemID : Int 
    var name : String 
    var animal : Animal 

    init(dictionary:[String:Any],animal:T) { 
     itemID = dictionary["itm_id"] as? Int ?? 0 
     name = dictionary["itm_name"] as? String ?? "" 
     self.animal = animal 
    } 
} 

然後你就可以初始化項目像

yourItem = Item(dictionary:yourDictionary,animal:Cat())

+0

不要將屬性聲明爲隱式解包可選,它們在'init'方法中用非可選值初始化。永遠不要這樣做。刪除感嘆號。 – vadian

0

//雨燕3.1

選項1:使用字典

func countRepeats() -> [[String: Int]] { 
    var repeats = [Int: Int]() 
    arr.forEach { item in 
     if let id = item["itm_id"] as? Int { 
      repeats[id] = repeats[id] == nil ? 1 : repeats[id]! + 1 
     } 
    } 
    return repeats.map {["item_id" : $0.key, "count": $0.value]} 
} 

print(countRepeats()) // [["item_id": 4, "count": 3], ["item_id": 7, "count": 1]] 

選項2:建議使用結構,而不是字典

public struct ItemCount { 
    let id: Int 
    let count: Int 
} 

func countRepeats() -> [ItemCount] { 
    var repeats = [Int: Int]() 
    arr.forEach { item in 
     if let id = item["itm_id"] as? Int { 
      repeats[id] = repeats[id] == nil ? 1 : repeats[id]! + 1 
     } 
    } 
    return repeats.map {ItemCount(id:$0.key, count: $0.value)} 
} 

print(countRepeats()) 
0

我建議在類(或結構),操縱你的數據,但如果你必須使用字典的數組,這裏是得到計數了一個辦法:

// extract all the "itm_id" values from all dictionaries in the array 
// use a set to identify unique values 
// map each unique values to its count in the array 

let ids = dictionaries.flatMap{$0["itm_id"] as? Int} 
let idCounts = Set(ids).map{ id in (id, ids.filter{$0==id}.count) } 

// You can use map() to turn this into yet another array of dictionaries 

let idCountDict = idCounts.map{["itm_id":$0 ,"count":$1]} 

print(idCounts)  // [(4, 3), (7, 1)] 
print(idCountDict) // [["itm_id": 4, "count": 3], ["itm_id": 7, "count": 1]]