Ilan Levy
Ilan Levy

Reputation: 191

how to extend Swift Dictionary of where K:String and V:String

I was thinking the following syntax:

extension Dictionary where Key:String,Value:String{
    func addIfNew(key:String,value:String){
      print("new item added: \(key) with value: \(value)")
    }
}

For example: the function would log any new added data

Upvotes: 8

Views: 11470

Answers (2)

user3441734
user3441734

Reputation: 17544

This should be enough ...

protocol P {}
extension String: P {}
extension Dictionary where Key:P, Value:P {
    func addIfNew(key:String, value:String){
        print("new item added: \(key) with value: \(value)")
    }
}

let d:[String:String] = [:]

don't make other types conforming to P and you are fine

in Swift3

extension Dictionary where Key == String, Value == String {
    func addIfNew(key:String, value:String){
        print("new item added: \(key) with value: \(value)")
    }
}
let d:[String:String] = [:]
d.addIfNew(key: "a", value: "A")

Upvotes: 15

R Menke
R Menke

Reputation: 8391

Not possible the way you want to do it. You can only constrain extensions of Dictionary to protocols Key and/or Value conform too. Else you will just get more errors.

But you can do this :

extension String : CustomStringConvertible {

    public var description : String { return self }

}

extension Dictionary where Key : CustomStringConvertible, Value : CustomStringConvertible {
    func addIfNew(key:Key,value:Value){
        print("new item added: \(key.description) with value: \(value.description)")
    }
}

var dict : [String:String] = [:]
dict["blah"] = "foo"
dict.addIfNew("blah", value: "foo2")

Important is to ask yourself what you want.

  • Only allow this function on Strings
  • Anything that is Equatable is good enough

If Equatable is good enough you can do this :

extension Dictionary where Value : Equatable {
    mutating func addIfNew(key:Key,value:Value){

        if self.values.contains(value) {
            print("\(value) exists")
        } else {
            print("new item added: \(key) with value: \(value)")
            self[key] = value
        }
    }
}

var dict : [String:String] = [:]
dict["blah"] = "foo"
dict.addIfNew("blah1", value: "foo2")
dict.addIfNew("blah2", value: "foo2")

Although this function will work on any Dictionary whose Value is Equatable, you can choose to only use it on those that have String as Value


If you really need it to only work on String you need to create a custom protocol and only have String conform to it. The protocol will need to have a computed property that returns self because else you will not be able to print it, since it isn't considered a String inside the extension.

protocol StringType : Hashable {

    var value : String { get }

}

extension String : StringType {

    var value : String { return self }

}

extension Dictionary where Key : StringType, Value : StringType {
    mutating func addIfNew(key:Key,value:Value){

        if self.values.contains(value) {
            print("\(value.value) exists")
        } else {
            print("new item added: \(key.value) with value: \(value.value)")
            self[key] = value
        }
    }
}

var dict : [String:String] = [:]
dict["blah"] = "foo"
dict.addIfNew("blah1", value: "foo2")
dict.addIfNew("blah2", value: "foo2") 

Side note:

Since Dictionary is a struct functions need to be mutating in order to alter self.

Upvotes: 7

Related Questions