xcode 从字典数组中删除重复项,Swift 3
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43790228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove duplicates from array of dictionaries, Swift 3
提问by mushy
Problem
问题
I have an array of dictionaries as follows:
我有一系列字典如下:
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"]
]
I need to remove all dictionaries where there is a duplicate name. For instance, I need an output of:
我需要删除所有有重复名称的字典。例如,我需要一个输出:
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"]
]
Order does not need to be preserved.
不需要保留订单。
Attempted Solution
尝试的解决方案
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)
}
}
}
This crashes though, I believe since I am modifying the size of arrayOfDicts, so eventually it j is larger than the size of the array.
虽然这会崩溃,但我相信因为我正在修改 arrayOfDicts 的大小,所以最终它 j 大于数组的大小。
If someone could help me out, that would be much appreciated.
如果有人可以帮助我,那将不胜感激。
回答by Leo Dabus
You can use a set to control which dictionaries to add to the resulting array. The approach it is very similar to the one used in these answerand this
您可以使用集合来控制将哪些字典添加到结果数组中。它的方法与这些答案中使用的方法非常相似,这
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.compactMap {
guard let name = 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
}
["Name"] as? String else { return nil }
return set.insert(name).inserted ? 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])
}
}
}
: 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"]]
回答by Connor
I definitely recommend having a new copy rather than modifying the initial array. I also create storage for names already used, so you should only need to loop once.
我绝对建议拥有一个新副本而不是修改初始数组。我还为已使用的名称创建存储,因此您只需要循环一次。
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{ let uniqueArray = Array(Set(yourArrayWithDuplicates))
})
}
回答by schinj
Please check this answer:
请检查这个答案:
var uniqueNames = [String: [String:String] ]()
for air in arrayOfDicts {
if (uniqueNames[arr["Name"]!] == nil) {
uniqueNames[arr["Name"]!] = arr
}
}
result = Array(uniqueNames.values)
回答by ghostatron
Several good answers already, but it was a fun exercise, so here's my solution. I'm assuming you don't care which of the duplicate entries are kept (this will keep the last one of the dupes).
已经有几个很好的答案,但这是一个有趣的练习,所以这是我的解决方案。我假设您不关心保留了哪些重复条目(这将保留最后一个重复条目)。
var uniqueArray = [[String: String]]()
for item in arrayOfDicts {
let exists = uniqueArray.contains{ element in
return element["Name"]! == item["Name"]!
}
if !exists {
uniqueArray.append(item)
}
}
回答by Fogmeister
That should do the trick.
这应该够了吧。
If you want to use just the name for uniqueness then create these as structs.
如果您只想使用名称的唯一性,则将它们创建为结构。
You shouldn't be doing anything with dictionaries. Much easier to work with data that makes sense.
你不应该对字典做任何事情。处理有意义的数据要容易得多。
回答by Dominic Bett
Try this:
尝试这个:
##代码##回答by janusfidel
If you don't mind using an additional list:
如果您不介意使用附加列表:
##代码##