How to filter values in dictionary of type [Type: [Type]]() - swift

I have a dictionary with multiple values and I want to filter through it for nil values. The type of dictionary is:
var dic = [Int: [String]]()
The dictionary is:
var dic = [218: ["A", "B", "C",""],216: ["Q", "", "W",""]]
//remove the empty values
let filter = dic.filter({ !$0.value.isEmpty})
print(filter)
It returns the same dictionary values with the nil values, which supposed to be removed.

It seems you need to filter the inner array from "" which is not nil but represents an empty string You need
let filter = dic.mapValues { $0.filter { $0 != "" } }

Related

Getting Array value in a dictionary swift

I am trying to get key and value in a Dictionary while I am able to the key and map it to a dictionary, I am unable to get the value which is an array.
var dict = [String: [String]]
I was able to get the key as an array which is what I want like:
var keyArray = self.dict.map { $0.key }
How can I get the value which is already an array
Use flatMap if you want to flatten the result you get when you use map which is of type [[String]].
let valueArray = dict.flatMap { $0.value } // gives `[String]` mapping all the values
Here is how you get each string count Array
var dict = [String: [String]]()
let countOfEachString = dict.map { $0.value }.map{ $0.count }
Each value is a string array .. so to access each array you need to use map again

Swift, Dictionary of String:String, best way to get an array of values, where the key contains a string?

I have a dictionary, like this:
{"Matt":"Apple", "Calvin":"Nut", "Susie":"Pear"}
I want to check the keys of the dictionary with a string, to see if they contain that string-- and if they do, I want to add their respective value to an array
So, if the input was "a"
the return would be ["Apple", "Nut"] because "Matt" and "Calvin" matched the "a"
Basically looking for some Swift tips,
otherwise I was going to implement it like this:
Grab all keys, put into an array
Filter keys for string value, this is the keyArray
Enumerate over keyArray, and get all their values from the dictionary
Boom have an array of values
You can filter the dictionary, using contains() on each key,
and then extract the corresponding values:
let dict = [ "Matt":"Apple", "Calvin":"Nut", "Susie":"Pear" ]
let input = "a"
let values = Array(dict.filter { $0.key.contains(input) }.values)
print(values) // ["Apple", "Nut"]
Or with flatMap() (renamed to compactMap() in Swift 4.1):
let values = dict.flatMap { $0.key.contains(input) ? $0.value : nil }
print(values) // ["Apple", "Nut"]
Here each dictionary entry is mapped to the value if the key contains
the given string, and to nil otherwise. flatMap() then returns an
array with the non-nil values.
Simply using a filter over the dictionary:
let dict: [String: String] = ["Matt": "Apple", "Calvin": "Nut", "Susie": "Pear"]
func findValuesMatching(search: String, in dict: [String: String]) -> [String] {
return dict
.filter { (key, value) in
return key.range(of: search) != nil
}.map { (key, value) in
return value
}
}
print(findValuesMatching(search: "a", in: dict))
Do it like this:
let dict = ["Matt":"Apple", "Calvin":"Nut", "Susie":"Pear"]
let containsA = dict.filter({ $0.key.lowercased().contains("a") }).map({ $0.value })
Output:
["Apple", "Nut"]

Basic Dictionary Operations in Swift [duplicate]

I'm trying to figure out the best way in Swift to add values to an Array that is a Value in a Dictionary. I want to build a dictionary of contacts sorted by the first letter of their first name. For example [A : [Aaron, Adam, etc...], B : [Brian, Brittany, ect...], ...]
I found this function:
updateValue(_:forKey:)
And tried using it in a loop:
for contact in self.contacts.sorted() {
self.contactDictionary.updateValue([contact], forKey: String(describing: contact.characters.first))
}
But when I tried to use that it replaced the existing array with a new one. I know I can manually check to see if the key in the dictionary exists, if it does, retrieve the array and then append a new value, otherwise add the new key/value pair but I'm not sure if Swift provides an easier/better way to do this.
Any insight would be much appreciated!
You can use reduce(into:) method (Swift4) and as follow:
let contacts = ["Aaron", "Adam", "Brian", "Brittany", ""]
let dictionary = contacts.reduce(into: [String:[String]]()) { result, element in
// make sure there is at least one letter in your string else return
guard let first = element.first else { return }
// create a string with that initial
let initial = String(first)
// initialize an array with one element or add another element to the existing value
result[initial] = (result[initial] ?? []) + [element]
}
print(dictionary) // ["B": ["Brian", "Brittany"], "A": ["Aaron", "Adam"]]
If you are using Swift3 or earlier you would need to create a mutable result dictionary inside the closure:
let contacts = ["Aaron", "Adam", "Brian", "Brittany", ""]
let dictionary = contacts.reduce([String:[String]]()) { result, element in
var result = result
guard let first = element.first else { return result }
let initial = String(first)
result[initial] = (result[initial] ?? []) + [element]
return result
}
print(dictionary) // ["B": ["Brian", "Brittany"], "A": ["Aaron", "Adam"]]
Note that the result is not sorted. A dictionary is an unordered collection. If you need to sort your dictionary and return an array of (key, Value) tuples you can use sorted by key as follow:
let sorted = dictionary.sorted {$0.key < $1.key}
print(sorted)
"[(key: "A", value: ["Aaron", "Adam"]), (key: "B", value: ["Brian", "Brittany"])]\n"
Swift 4's new dictionary initializers can do it all for you:
let contactInitials = contacts.filter{!$0.isEmpty}.map{ ($0.first!,[$0]) }
let dict = [Character:[String]](contactInitials, uniquingKeysWith:+)

Adding items to Array as a Dictionary Value

I'm trying to figure out the best way in Swift to add values to an Array that is a Value in a Dictionary. I want to build a dictionary of contacts sorted by the first letter of their first name. For example [A : [Aaron, Adam, etc...], B : [Brian, Brittany, ect...], ...]
I found this function:
updateValue(_:forKey:)
And tried using it in a loop:
for contact in self.contacts.sorted() {
self.contactDictionary.updateValue([contact], forKey: String(describing: contact.characters.first))
}
But when I tried to use that it replaced the existing array with a new one. I know I can manually check to see if the key in the dictionary exists, if it does, retrieve the array and then append a new value, otherwise add the new key/value pair but I'm not sure if Swift provides an easier/better way to do this.
Any insight would be much appreciated!
You can use reduce(into:) method (Swift4) and as follow:
let contacts = ["Aaron", "Adam", "Brian", "Brittany", ""]
let dictionary = contacts.reduce(into: [String:[String]]()) { result, element in
// make sure there is at least one letter in your string else return
guard let first = element.first else { return }
// create a string with that initial
let initial = String(first)
// initialize an array with one element or add another element to the existing value
result[initial] = (result[initial] ?? []) + [element]
}
print(dictionary) // ["B": ["Brian", "Brittany"], "A": ["Aaron", "Adam"]]
If you are using Swift3 or earlier you would need to create a mutable result dictionary inside the closure:
let contacts = ["Aaron", "Adam", "Brian", "Brittany", ""]
let dictionary = contacts.reduce([String:[String]]()) { result, element in
var result = result
guard let first = element.first else { return result }
let initial = String(first)
result[initial] = (result[initial] ?? []) + [element]
return result
}
print(dictionary) // ["B": ["Brian", "Brittany"], "A": ["Aaron", "Adam"]]
Note that the result is not sorted. A dictionary is an unordered collection. If you need to sort your dictionary and return an array of (key, Value) tuples you can use sorted by key as follow:
let sorted = dictionary.sorted {$0.key < $1.key}
print(sorted)
"[(key: "A", value: ["Aaron", "Adam"]), (key: "B", value: ["Brian", "Brittany"])]\n"
Swift 4's new dictionary initializers can do it all for you:
let contactInitials = contacts.filter{!$0.isEmpty}.map{ ($0.first!,[$0]) }
let dict = [Character:[String]](contactInitials, uniquingKeysWith:+)

accessing inner dictionaries (dictionary of dictionaries) with one entry, when not knowing what key or value for that entry are

This is how I declared my dictionary:
var dataDictionary: [NSIndexPath:[Int:Bool]]!
The inner dictionary will always have just one entry e.g. [1:true]. When I search dataDictionary I specify a NSIndexPath. The inner dictionary gets returned. Sth like this:
var innerDictionary = dataDictionary[indexPath] // is of type [Int:Bool]
I would like to access inner dictionarys key and value, but I don't want to specify an Integer or Bool, because it is unknown. I only want to get that Int and/or Bool value stored in inner dictionary. No search of inner dictionary is needed, because if will always contains just one entry. Maybe something like this:
var key = innerDictionary.key
var value = innerDictionary.value
How can this be accomplished?
If your dictionary has only one entry, and you don't know the key, with Swift 2 you can get the first element of the keys sequence safely with if let:
let innerDictionary = [42: true]
if let k = innerDictionary.keys.first {
print(k) // prints 42
} else {
// dict is empty
}
Same for the value:
if let v = innerDictionary.values.first {
print(v) // prints true
} else {
// key has no value
}
Try by this way:
func nestedDic(){
var innerDictionary:NSDictionary = ["Item 1": "data 0", "Item 2": "data 1"]
//NSLog("original object:\(innerDictionary)")
NSLog("all keys array:\(innerDictionary.allKeys)")
if(innerDictionary.isKindOfClass(NSDictionary)){
for key in innerDictionary.allKeys{
let value = innerDictionary.valueForKey(key as! NSString as String)
NSLog("key value = \(value as! String)")
}
}
}
You could create a simple struct for the inner dictionary if there is only one entry, then you are able to use your favorite property names.
struct InnerDictionary {
var key = 0
var value = false
}
let indexPath = NSIndexPath(index: 1)
var dataDictionary = [indexPath: InnerDictionary(key: 1, value: true)]
if let innerDictionary = dataDictionary[indexPath] {
var key = innerDictionary.key
var value = innerDictionary.value
}