How to Avoid Duplicate Key Error in Swift When Iterating Over a Dictionary

How to avoid duplicate key error in swift when iterating over a dictionary

Each dictionary key MUST be unique

let people = ["age1":14, "age2":15, "age3":75, "age4":43, "age5":103, "age6":87, "age7":12]
for (key, value) in people {
print(value)
}

Dictionary literal contains duplicate keys

Here's a way to find the culprit without changing all the original literals:

First, set the type of the array of dictionaries as follows:

let dictionaries : [DictionaryLiteral<String, AnyObject>] = [
[
"id": "1",
...

Then run the following code:

for (i, dict) in dictionaries.enumerate() {
var keys = Set<String>()
for (key, _) in dict {
if keys.contains(key) {
print("dict[\(i)] contains duplicate key: \"\(key)\"")
} else {
keys.insert(key)
}
}
}

I should point you to the duplicate keys.

Duplicate keys of type ... were found in a Dictionary when there is no Dictionary?

I think you are missing a full conformance to the Hashable Protocol

Pay attention to the func hash(into hasher: inout Hasher) function which you are missing

iterating over a dictionary in Swift

If you add a print of names and numbers directly in the outer loop you will realise there is no need to loop over names as you do and neither is it necessary to try to use the dictionary again inside the loop.

So we could skip one loop ands directly use the names variable to remember the name of the largest value array. And furthermore there is no reason to loop over the numbers array either since Array has a max() function we can use.

So the code becomes

for (names, numbers) in interestingNumbers {
if let max = numbers.max(), max > largest {
largest = max
largestName = names
}
}

An even short way to do it is to use some high-order functions to get the max value

interestingNumbers.mapValues({ $0.max() ?? 0 }).max(by: { $0.value < $1.value}) 

This will return a tuple and can be used like this

if let tuple = interestingNumbers.mapValues({ $0.max() ?? 0 }).max(by: { $0.value < $1.value})  {
largest = tuple.1
largestName = tuple.0
}

Remove duplicate values from a dictionary in Swift 3

It looks to me like all the other answers will have O(n^2) performance.

Here is a solution that should operate in O(n) time:

var sourceDict = [1:"test1", 2:"test2", 3:"test1", 4:"test4"]

var uniqueValues = Set<String>()
var resultDict = [Int:String](minimumCapacity: sourceDict.count)

//The reserveCapacity() function doesn't exist for Dictionaries, as pointed
//out by Hamish in the comments. See the initializer with minimumCapacity,
//above. That's the way you have to set up a dictionary with an initial capacity.
//resultDict.reserveCapacity(sourceDict.count)

for (key, value) in sourceDict {
if !uniqueValues.contains(value) {
uniqueValues.insert(value)
resultDict[key] = value
}
}

For small dictionaries the difference is insignificant, but if you have a dictionary with hundreds (or thousands) of key/value pairs then the performance of an n^2 algorithm starts to get really bad.

To Call webAPI in Swift & fatal error: dictionary literal contains duplicate keys

Your Swift code is fundamentally different from the Obj-C code. The Swift equivalent
to

NSString *post =[[NSString alloc] initWithFormat:@"FirstName=%@&ContactNumber=%@&Email=%@&password=%@&password=%@&Rd_UserType=%@",Name.text,ContactNumber.text,EmailAddress.text,Password.text,ReTypePassword.text,type];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];

would be something like

let post = "FirstName=\(Name.text)&ContactNumber=\(ContactNumber.text)&..."
let postData = post.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)!
let postLength = "\(postData.length)"

You are creating a JSON dictionary as post data instead. That fails because a
dictionary cannot have two values for the same key. Also JSON might not be
what the server expects.

Swift runtime error: Dictionary literal contains duplicate keys

My original code compiles, but for some reason these are runtime "constants" that change values from 0 to something else at an unknown point.

I postponed the construction of the dictionary to after initialization of my object, and it works.

var propertyToMethod: [ABPropertyID : String] { get {
println("kabIM: \(kABPersonInstantMessageProperty), kabEmail: \(kABPersonEmailProperty), kabPhone: \(kABPersonPhoneProperty)")
return [ kABPersonInstantMessageProperty : contactMethodInstantMessage,
kABPersonEmailProperty : contactMethodEmail,
kABPersonPhoneProperty : contactMethodPhoneCall ] }
}

But I still can't be sure that it won't crash in the future...



Related Topics



Leave a reply



Submit