Swift 3 Filter Array of Dictionaries by String Value of Key in Dictionary

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

  1. Don't use NSArray or NSMutableArray in Swift. Use Swift native arrays (and dictionaries).
  2. Once you do that, there is no need for NSPredicate. Use the filter method.
  3. 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 to index(where:
  • filteredArrayUsingPredicate(predicate) has been renamed to filtered(using: predicate)


Related Topics



Leave a reply



Submit