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"]]
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]
I filtered an NSMutableArray of Dictionaries and then I want to filter for a Key again
- Don't use
NSArray
orNSMutableArray
in Swift. Use Swift native arrays (and dictionaries). - Once you do that, there is no need for
NSPredicate
. Use thefilter
method. - Don't use a dictionary to hold your data. Create a
struct
with the needed fields.
First, without creating a struct
, here's a simply solution using native arrays:
var dataArray = [[String:Any]]()
var sum = 0.00
func addNewIncomeRecord(_ id: String, date: String, description: String, amount: Double, currency: String, category: String, notes: String) {
let dict: [String:Any] = ["id" : id, "date" : date, "description" : description, "amount" : amount, "currency" : currency, "category" : category, "notes" : notes]
dataArray.append(dict)
}
addNewIncomeRecord("1", date: "11-25", description: "Money", amount: 20.00, currency: "EUR", category: "Home", notes: "More Money")
addNewIncomeRecord("2", date: "11-25", description: "Rent", amount: 50.00, currency: "EUR", category: "Home", notes: "Rent Money")
addNewIncomeRecord("3", date: "11-25", description: "Hair", amount: 10.00, currency: "EUR", category: "Medical" ,notes: "HairCut")
let filteredArray = dataArray.filter { $0["category"] as? String == "Home" }
let amounts = filteredArray.flatMap { $0["amount"] as? Double }
print(amounts)
Here's the solution making use of a struct
.
struct Income {
let id: String
let date: String
let description: String
let amount: Double
let currency: String
let category: String
let notes: String
}
var dataArray = [Income]()
var sum = 0.00
func addNewIncomeRecord(_ id: String, date: String, description: String, amount: Double, currency: String, category: String, notes: String) {
let income = Income(id: id, date: date, description: description, amount: amount, currency: currency, category: category, notes: notes)
dataArray.append(income)
}
addNewIncomeRecord("1", date: "11-25", description: "Money", amount: 20.00, currency: "EUR", category: "Home", notes: "More Money")
addNewIncomeRecord("2", date: "11-25", description: "Rent", amount: 50.00, currency: "EUR", category: "Home", notes: "Rent Money")
addNewIncomeRecord("3", date: "11-25", description: "Hair", amount: 10.00, currency: "EUR", category: "Medical" ,notes: "HairCut")
let filteredArray = dataArray.filter { $0.category == "Home" }
let amounts = filteredArray.map { $0.amount }
print(amounts)
Using a struct
has many advantages. It's type safe for each field. You can make it Codable
which makes it a lot easier to save and read from a file.
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!"
Swift filter dictionary error: Cannot assign a value of type '[(_, _)]' to a value of type '[_ : _]'
This has been fixed in Swift 4
let data = ["a": 0, "b": 42]
let filtered = data.filter { $0.value > 10 }
print(filtered) // ["b": 42]
In Swift 4, a filtered dictionary returns a dictionary.
Original answer for Swift 2 and 3
The problem is that data
is a dictionary but the result of filter
is an array, so the error message says that you can't assign the result of the latter to the former.
You could just create a new variable/constant for your resulting array:
let data: [String: String] = [:]
let filtered = data.filter { $0.1 == "Test" }
Here filtered
is an array of tuples: [(String, String)]
.
Once filtered, you can recreate a new dictionary if this is what you need:
var newData = [String:String]()
for result in filtered {
newData[result.0] = result.1
}
If you decide not to use filter
you could mutate your original dictionary or a copy of it:
var data = ["a":"Test", "b":"nope"]
for (key, value) in data {
if value != "Test" {
data.removeValueForKey(key)
}
}
print(data) // ["a": "Test"]
Note: in Swift 3, removeValueForKey
has been renamed removeValue(forKey:)
, so in this example it becomes data.removeValue(forKey: key)
.
Search in Array of Dictionaries by key name
Use the filter
function
let foo = [
["selectedSegment":0, "severity":3, "dataDictKey": "critical"],
["selectedSegment":1, "severity":2, "dataDictKey": "major"],
["selectedSegment":2, "severity":1, "dataDictKey": "minor"],
]
let filteredArray = foo.filter{$0["severity"]! == 2}
print(filteredArray.first ?? "Item not found")
or indexOf
if let filteredArrayIndex = foo.indexOf({$0["severity"]! == 2}) {
print(foo[filteredArrayIndex])
} else {
print("Item not found")
}
or NSPredicate
let predicate = NSPredicate(format: "severity == 2")
let filteredArray = (foo as NSArray).filteredArrayUsingPredicate(predicate)
print(filteredArray.first ?? "Item not found")
Swift 3 Update:
indexOf(
has been renamed toindex(where:
filteredArrayUsingPredicate(predicate)
has been renamed tofiltered(using: predicate)
Related Topics
Mirror Not Working in Swift When Iterating Through Children of an Objective-C Object
Horizontal Paging Uicollectionview with Automatic Item Size in a Vertical Stack View
Storyboard Localization in Swift 4.0
Records, Zone Doesn't Displayed in Dashboard and Delete Zone Issue Cloudkit
How to Cluster Custom Icons Markers in Googlemaps for iOS
How to Set the Local Storage Before a Uiwebview Loading Its Initial Request
Collectionview Flowlayout Overlapping When Scrolling Not Working
How to Send Request from iOS (Swift) to Dialogflow V2 API Without Cloud Functions
How to Change Uinavigationbar Per View Controller
Swift - How to Open Another Viewcontroller with Collectionviewcell Inside Uitableviewcell
Xcode 9: Swift Dependency Analysis Error
Programmatically Obtaining the Imei or Udid of an iOS Device
Swift3 - How to Protect Secret Key
Subview Gesture Recognizer Not Being Called
Skaction Works in Didmovetoview But Doesn't Works in Function
Passing Data Between Views in One Viewcontroller in Swift
iOS Pass Data Back from Viewcontroller2 to Viewcontroller 1 with Presentmodalsegue