从字典数组中删除重复项,Swift 3

时间:2017-05-04 18:24:46

标签: ios swift xcode

问题

我有一系列字典如下:

var arrayOfDicts = [
    ["Id":"01", "Name":"Alice", "Age":"15"]
    ["Id":"02", "Name":"Bob", "Age":"53"]
    ["Id":"03", "Name":"Cathy", "Age":"12"]
    ["Id":"04", "Name":"Bob", "Age":"83"]
    ["Id":"05", "Name":"Denise", "Age":"88"]
    ["Id":"06", "Name":"Alice", "Age":"44"]
]

我需要删除名称重复的所有词典。例如,我需要输出:

var arrayOfDicts = [
    ["Id":"01", "Name":"Alice", "Age":"15"]
    ["Id":"02", "Name":"Bob", "Age":"53"]
    ["Id":"03", "Name":"Cathy", "Age":"12"]
    ["Id":"05", "Name":"Denise", "Age":"88"]
]

不需要保留订单。

尝试解决方案

for i in 0..<arrayOfDicts.count
{
    let name1:String = arrayOfDicts[i]["Name"]

    for j in 0..<arrayOfDicts.count
    {
        let name2:String = arrayOfDicts[j]["Name"]

        if (i != j) && (name1 == name2)
        {
            arrayOfDicts.remove(j)
        }
    }
} 

虽然崩溃,我相信因为我正在修改arrayOfDicts的大小,所以最终它j大于数组的大小。

如果有人可以帮助我,那将非常感激。

7 个答案:

答案 0 :(得分:6)

我绝对建议使用新副本而不是修改初始数组。我还为已经使用的名称创建存储空间,因此您只需要循环一次。

func noDuplicates(_ arrayOfDicts: [[String: String]]) -> [[String: String]] {
    var noDuplicates = [[String: String]]()
    var usedNames = [String]()
    for dict in arrayOfDicts {
        if let name = dict["name"], !usedNames.contains(name) {
            noDuplicates.append(dict)
            usedNames.append(name)
        }
    }
    return noDuplicates
}

答案 1 :(得分:5)

您可以使用一个集来控制要添加到结果数组的字典。该方法与这些answerthis

中使用的方法非常相似
let array: [[String : Any]] = [["Id":"01", "Name":"Alice", "Age":"15"],
                                ["Id":"02", "Name":"Bob", "Age":"53"],
                                ["Id":"03", "Name":"Cathy", "Age":"12"],
                                ["Id":"04", "Name":"Bob", "Age":"83"],
                                ["Id":"05", "Name":"Denise", "Age":"88"],
                                ["Id":"06", "Name":"Alice", "Age":"44"]]

var set = Set<String>()
let arraySet: [[String : Any]] = array.flatMap {
    guard let name = $0["Name"] as? String else {return nil }
    return set.insert(name).inserted ? $0 : nil
}

arraySet   // [["Name": "Alice", "Age": "15", "Id": "01"], ["Name": "Bob", "Age": "53", "Id": "02"], ["Name": "Cathy", "Age": "12", "Id": "03"], ["Name": "Denise", "Age": "88", "Id": "05"]]

答案 2 :(得分:1)

请检查这个答案:

var arrayOfDicts = [
    ["Id":"01", "Name":"Alice", "Age":"15"],
    ["Id":"02", "Name":"Bob", "Age":"53"],
    ["Id":"03", "Name":"Cathy", "Age":"12"],
    ["Id":"04", "Name":"Bob", "Age":"83"],
    ["Id":"05", "Name":"Denise", "Age":"88"],
    ["Id":"06", "Name":"Alice", "Age":"44"]
]

var answerArray = [[String:String]]()

for i in 0..<arrayOfDicts.count
{
    let name1 = arrayOfDicts[i]["Name"]
    if(i == 0){
        answerArray.append(arrayOfDicts[i])
    }else{
        var doesExist = false
        for j in 0..<answerArray.count
        {
            let name2:String = answerArray[j]["Name"]!
            if name1 == name2 {
                doesExist = true
            }
        }
        if(!doesExist){
            answerArray.append(arrayOfDicts[i])
        }
    }
}

答案 3 :(得分:0)

已有几个好的答案,但这是一个有趣的练习,所以这是我的解决方案。我假设你不关心保留哪些重复的条目(这将保留最后一个欺骗)。

func noDuplicates(arrayOfDicts: [[String:String]]) -> [[String:String]]
{
    var noDuplicates: [String:[String:String]] = [:]
    for dict in arrayOfDicts
    {
        if let name = dict["name"]
        {
            noDuplicates[name] = dict
        }
    }

    // Returns just the values of the dictionary
    return Array(noDuplicates.values.map{ $0 })
}

答案 4 :(得分:0)

@OnClick({R.id.registerDateBirthInptLay, R.id.registerDateBirthEdtTxt})
void selectBirthDay() {

这应该可以解决问题。

如果您只想使用唯一性名称,请将其创建为结构。

你不应该用词典做任何事情。使用有意义的数据更容易处理。

答案 5 :(得分:0)

试试这个:

var uniqueNames = [String: [String:String] ]()

for air in arrayOfDicts {
    if (uniqueNames[arr["Name"]!] == nil) {
        uniqueNames[arr["Name"]!] = arr
    }
}

result = Array(uniqueNames.values)

答案 6 :(得分:0)

如果您不介意使用其他列表:

var uniqueArray = [[String: String]]()
for item in arrayOfDicts {
    let exists =  uniqueArray.contains{ element in
        return element["Name"]! == item["Name"]!
    }
    if !exists {
      uniqueArray.append(item)
    }
}