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: 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"]]
Filtering an Array inside a Dictionary - Swift
The main problem is that you are using a dictionary as data source array.
My suggestion is to use a custom struct as model
struct Contact {
let letter : String
var clients : [Client]
init(letter: String, clients : [Client] = [Client]()) {
self.letter = letter
self.clients = clients
}
mutating func add(client : Client) {
clients.append(client)
}
}
Then create your data source array
var contacts = [Contact]()
and the letter array as computed property
var letters : [String] = {
return contacts.map{ $0.letter }
}
It's easy to sort the array by letter
contacts.sort{ $0.letter < $1.letter }
Now you can search / filter this way (text
is the text to be searched for)
filteredClient.removeAll()
for contact in contacts {
let filteredContent = contact.clients.filter {$0.name.range(of: text, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil }
if !filteredContent.isEmpty {
filteredClient.append(filteredContent)
}
}
You can even keep the sections (letters) if you declare filteredClient
also as [Contact]
and create temporary Contact
instances with the filtered items.
Of course you need to change all table view data source / delegate methods to conform to the Contact
array, but it's worth it. An array as data source is more efficient than a dictionary.
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 array of dictionaries - SWIFT
let test = [["user1ID": NSDate()], ["user2ID": NSDate()], ["user3ID": NSDate()]]
let newArray = test.filter { $0.keys.contains("user2ID") }.flatMap { $0 }
print(newArray) // ["user2ID": 2016-01-28 10:52:29 +0000]
I've edited your dictionary a bit for testing purposes.
Answer to your comment:
If you simply want to know if the array contains a dictionary with "user2ID" as key you can do the following:
test.contains { $0.keys.contains("user2ID") } ? print("yep!") : print("nope!") // "Yep!"
Chaining filter and map array by dictionary values in Swift
Assuming Object
is a struct
, based on the error message...
This just shows that higher-order functions shouldn't be used everywhere. map
transforms each element in a sequence into something else. So instead of assigning score
, you need to return a new Object
with its score
changed.
var scoresAssigned = filteredObjects.map { $0.withScore(scoreDict[$0.id.uuidString.lowercased()]) }
withScore
will look something like:
func withScore(_ score: Int) -> Object {
var copy = self
copy.score = score
return copy
}
But, if you just want to assign the score a new value, I recommend a simple for loop.
for i in 0..<filteredObjects.count {
filteredObjects[i].score = scoreDict[$0.id.uuidString.lowercased()]
}
Also note that you only need to access the dictionary once. If it's nil, the key doesn't exist.
var filteredObjects = [Object]()
for i in 0..<objects.count {
if let score = scoreDict[$0.id.uuidString.lowercased()] {
objects[i].score = score
filteredObjects.append(objects[i])
}
}
Related Topics
Swift Xcode 7 Beta 5 Type Cannot Refer to Itself as a Requirement
How Does Swift Disambiguate Type Arguments in Expression Contexts
Http Status 415 When Using Alamofire Multipart Upload
Swift 4 "Extra Argument in Call" Rxswift
Covert Realm List to Realm Result
Swift Set UIbutton Setbordercolor in Storyboard
Argument of '#Selector' Does Not Refer to an '@Objc' Method (Swift 3)
How to Convert String to Date Without Time in Swift 3
Implementing Undo and Redo in a UItextview with Attributedtext
How to Reconnect Akplayer and Akmixer After Audiokit.Stop()
Arkit/Scenekit on iOS 14 Throws New Warning (Metal)
Problem with Swiftui and Foreach on Xcode Playground
Why Swift Disallows Weak Reference for Non-Optional Type
Bool.Hashvalue Valid to Convert to Int
Adding Constraints Programmatically in UIview with UItextview
#If Canimport(Coreimage) Not Working in Swift Package Manager