Swift: Filter a Dictionary with Array as Value
Here's a solution that maps the values based on the search and then filters out the empty results.
var dictionary = ["a": ["aberration", "abc"], "b" : ["babel", "bereft"]]
var searchText = "aberration"
let filteredDictionary = dictionary.mapValues { $0.filter { $0.hasPrefix(searchText) } }.filter { !$0.value.isEmpty }
print(filteredDictionary)
Output:
["a": ["aberration"]]
swift 3 filter array of dictionaries by string value of key in dictionary
I hope I understood what you were asking. You mention an "array of dictionaries" but you don't actually have an array of dictionaries anywhere in the code you've posted.
As far as I can tell, you are asking how to find all the entries in the found
array for which itemName
equals the filterItemName
property.
If so, all you should need to do is:
let foundItems = found.filter { $0.itemName == filterItemName }
That's it.
Some other ideas:
If you want to search for items where filterItemName
is contained in the itemName
, you could do something like this:
let foundItems = found.filter { $0.itemName.contains(filterItemName) }
You could also make use of the lowercased()
function if you want to do case-insensitive search.
You could also return properties of your found elements into an array:
let foundIds = found.filter { $0.itemName == filterItemName }.map { $0.itemId }
Swift: is there an elegant way to filter a dictionary value (which is an array)?
You can use mapValues
and then filter
for the actual values
let output = i.mapValues { $0.filter { value in value < 7 } }
Filter Array of Dictionary Objects by key and last value of that specified key
This can be done by grouping the elements based on the inner dictionary key and then selecting the last element of each group
let selected = Dictionary(grouping: randomData, by: { $0.keys.first })
.compactMap { $0.value.last }
As suggested by @Alexander in the comments this can be solved more directly using Dictionary(_:uniqueKeysWith:)
let selected = Dictionary(randomData.flatMap { $0 }, uniquingKeysWith: {
return $0 > $1 ? $0 : $1
})
The two solutions yield a slightly different result, the first an array of dictionaries and the second one a dictionary as can be seen below
First solution: [[2: 0.5237581], [4: 0.5928725], [5: 0.32073426], [0: 0.3142548]]
Second solution: [0: 0.3142548, 5: 0.32073426, 4: 0.5928725, 2: 0.5237581]
Filter dictionary of array objects
I decided it was simplest to get this right by using an old fashioned for
loop and filter each group separately
var filtered = [String: [People]]()
for (k, v) in dict {
let result = v.filter {$0.name.lowercased().contains("ata")}
if result.count > 0 {
filtered[k] = result
}
}
Note that if you want to keep all the groups in the result dictionary just skip the if result.count > 0
condition
Filter a dictionary with a nested dictionary in Swift 5
To give you some examples how to filter I created a set of data from the winner and runner up in the Champions League tournament. In the main dictionary the Int
key correspond to the tournament's year. The dictionary inside has two keys: 1stPlace
and 2ndPlace
. So for example in 2018 Real Madrid defeated Liverpool, the dictionary will look like this:
2018: ["1stPlace": "Real Madrid", "2ndPlace": "Liverpool"]
Assuming this structure the Data
variable has the results from 2018 to 2011. If you want to know who won in 2018 you can do something like this:
filteredData = Data.filter { $0.key == 2018 }
If you want know when Real Madrid won you doo like this:
filteredData = Data.filter { $0.value["1stPlace"] == "Real Madrid" }
If you want to know when Real Madrid defeated Atlético Madrid you do it like this:
filteredData = Data.filter {
$0.value["2ndPlace"] == "Atlético Madrid" &&
$0.value["1stPlace"] == "Real Madrid"
}
When you have the results in filteredData
you can do query the data in different ways: you can sort by year, you can extract just the years, etc.
The following code is the playground I used to test different kinds of queries:
import Foundation
typealias DictOfDicts = [Int : [String : String]]
var Data: DictOfDicts = [
2018:
["1stPlace": "Real Madrid", "2ndPlace": "Liverpool"],
2017:
["1stPlace": "Real Madrid", "2ndPlace": "Juventus"],
2016:
["1stPlace": "Real Madrid", "2ndPlace": "Atlético Madrid"],
2015:
["1stPlace": "Barcelona", "2ndPlace": "Juventus"],
2014:
["1stPlace": "Real Madrid", "2ndPlace": "Atlético Madrid"],
2013:
["1stPlace": "Bayern Munich", "2ndPlace": "Borussia Dortmund"],
2012:
["1stPlace": "Chelsea", "2ndPlace": "Bayern Munich"],
2011:
["1stPlace": "Barcelona", "2ndPlace": "Manchester United"]
]
var filteredData: DictOfDicts = [:]
print("Results from 2017 to present")
print("----------------------------")
filteredData = Data.filter { $0.key >= 2017 } // Filter from 2017 to present
filteredData
.sorted { $0.key > $1.key } // Sort by year
.forEach {
print("In \($0.key) \($0.value["1stPlace"]!) defeated \($0.value["2ndPlace"]!)")
}
print("")
print("Results before 2015")
print("----------------------------")
filteredData = Data.filter { $0.key < 2015 } // Filter before 2015
filteredData
.sorted { $0.key > $1.key } // Sort by year
.forEach {
print("In \($0.key) \($0.value["1stPlace"]!) defeated \($0.value["2ndPlace"]!)")
}
print("")
filteredData = Data.filter { $0.value["1stPlace"] == "Real Madrid" } // Filter Real Madrid won
var years = filteredData
.sorted { $0.key < $1.key } // Sort by year
.map { "\($0.key)" } // Convert year to string
.joined(separator: ", ") // Convert to comma separated single string
print("Real Madrid won in: \(years)")
print("")
filteredData = Data.filter { $0.value["2ndPlace"] == "Juventus" } // Filter Juventus lost
years = filteredData
.sorted { $0.key > $1.key } // Sort by year
.map { "\($0.key)" } // Convert year to string
.joined(separator: ", ") // Convert to comma separated single string
print("Juventus lost the final match in: \(years)")
print("")
filteredData = Data.filter {
$0.value["2ndPlace"] == "Atlético Madrid" &&
$0.value["1stPlace"] == "Real Madrid"
} // Filter Real Madrid defeated Atlético Madrid
years = filteredData
.sorted { $0.key > $1.key } // Sort by year
.map { "\($0.key)" } // Convert year to string
.joined(separator: ", ") // Convert to comma separated single string
print("Real Madrid defeated Atlético Madrid in: \(years)")
print()
let winnersAndChampionships =
Set(Data.map { $0.value["1stPlace"]! }) // Get winners' names
.map { winner in
(winner, Data.filter { $0.value["1stPlace"] == winner }.count)
} // Map for each winner the number of wins
.sorted { $0.1 > $1.1}
print("Number of Champions League's wins per team")
print("------------------------------------------")
winnersAndChampionships.forEach {
print("\($0.0): \($0.1)")
}
The playground's output is:
Results from 2017 to present
----------------------------
In 2018 Real Madrid defeated Liverpool
In 2017 Real Madrid defeated Juventus
Results before 2015
----------------------------
In 2014 Real Madrid defeated Atlético Madrid
In 2013 Bayern Munich defeated Borussia Dortmund
In 2012 Chelsea defeated Bayern Munich
In 2011 Barcelona defeated Manchester United
Real Madrid won in: 2014, 2016, 2017, 2018
Juventus lost the final match in: 2017, 2015
Real Madrid defeated Atlético Madrid in: 2016, 2014
Number of Champions League's wins per team
------------------------------------------
Real Madrid: 4
Barcelona: 2
Bayern Munich: 1
Chelsea: 1
Swift: Filter a dictionary key from a struct from an array, which is optional
It's not completely clear to me what you're attempting to do, however, this will filter your cases
array to only Test
objects that contain non-nil values
in the message dictionary:
let nonNil = cases.filter { (test) -> Bool in
return Array(test.message.values).filter({ (value) -> Bool in
return value == nil
}).count <= 0
}
The variable nonNil
now contains the Test
objects where title is "2" and title is "4".
You could further filter that if you want a [tags:preview]
dictionary. Something like this would do that:
let tags = nonNil.map( { $0.message} ).flatMap { $0 }.reduce([String:String]()) { (accumulator, current) -> [String:String] in
guard let key = current.key, let value = current.value else { return accumulator }
var accum = accumulator
accum.updateValue(value, forKey: key)
return accum
}
The tags
dictionary now contains: ["tag1": "preview4", "tag2": "preview2"]
Swift filter and dictionaries
Just do it like this:
var namesAndAges = ["Tom": 25, "Michael": 35, "Harry": 28, "Fabien": 16]
var underAge = namesAndAges.filter({ $0.value < 18 }) // [(key: "Fabien", value: 16)]
What you do is that you use $0.value
in your filter
.
Related Topics
How to Stop an Infinitely Rotating Image? and How Does One Implement Removeallanimations
Create a Weak Container in Swift That Accepts a Native Swift Protocol
Convert Integer to Roman Numeral String in Swift
How to Group an Array of Image Urls Together in Firebase Realtime Database? (Swift)
Swift: Download Image from Internet and Cache Them Doesn't Work Properly. Need Suggestions
Swift Interstitial Making a Banner Ad
Aws Cognito/Getting User Information from the Sub
Can't Append Value to My Nsarray Variable
How to Disambiguate a Foreach Loop in Xcode with Swiftui
How to Change Uitextfield Keyboard Type to Email in Swift
Passing Unknown Number of Arguments in a Function
How to Display an Image by an API Url? Swift
Undefined Symbol Objc_Class_$ When Creating iOS Framework
Getting the Time Remaining in the Time Interval of a Timer in Swift
Interrupted Purchase Not Calling Delegate After Accepting T&C
Swift Uikit Dynamics Add Collision Boundary. After Rotation Does Not Work Correctly
Swift Generic Func Cannot Convert Value of Type to Expected Argument Type