Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift 3 filter array of dictionaries by string value of key in dictionary

I have a class such as this

class FoundItem : NSObject {

var id : String!
var itemName : String!
var itemId : Int!
var foundBy : String!
var timeFound : String!

init(id: String,
    itemName: String,
    itemId: Int,
    foundBy: String,
    timeFound: String)

{
    self.id = id
    self.itemName = itemName
    self.itemId = itemId
    self.foundBy = foundBy
    self.timeFound = timeFound

}

and I reference it on my

class MapViewVC: UIViewController, MKMapViewDelegate {

var found = [FoundItem]()

var filterItemName : String()

}

My FoundItem are generated by into an array of dictionaries from my class of FoundItem from a firebase query. I then get a string of that itemName that is generated from an another view controller that is a collection view on the didSelection function. I want to take that string and then filter or search the arrays with the string itemName that is equal from the itemName string from my previous viewController. Then removed the array of dictionaries that are not equal to the itemName. Not just the objects, but the entire array that contains non-equal key, value pair. I have looked for days, and I am stuck on filtering an array of dictionaries created from a class. I have looked and tried NSPredicates, for-in loops, but all that ends up happening is creating a new array or bool that finds my values or keys are equal. Here is the current function I have written.

func filterArrayBySearch() {

    if self.filterItemName != nil {

        dump(found)

        let namePredicate = NSPredicate(format: "itemName like %@", "\(filterItemName)")
        let nameFilter = found.filter { namePredicate.evaluate(with: $0) }

        var crossRefNames = [String: [FoundItem]]()
        for nameItemArr in found {
            let listName = nameItem.itemName
            let key = listName

            if crossRefNames.index(forKey: key!) != nil {

                crossRefNames[key!]?.append(nameItemArr)

                if !("\(key)" == "\(filterItemName!)") {

                    print("------------- Success have found [[[[[[    \(key!)    ]]]]]] and \(filterItemName!) to be equal!!")

                     // crossRefNames[key!]?.append(nameItemArr)

                } else {

                    print("!! Could not find if \(key!) and \(filterItemName!) are equal !!")
                }


            } else {

                crossRefNames[key!] = [nameItemArr]
            }
        }

    } else {

        print("No Data from Search/FilterVC Controller")
    }
}

Can anyone help? It seems like it would be the simple task to find the value and then filter out the dictionaries that are not equal to the itemName string, but I keep hitting a wall. And running into for-in loops myself :P trying different things to achieve the same task.

like image 573
Cory Billeaud Avatar asked Nov 13 '16 04:11

Cory Billeaud


2 Answers

Sort array of dictionary using the following way

var dict:[[String:AnyObject]] = sortedArray.filter{($0["parentId"] as! String) == "compareId"}

The filter function loops over every item in a collection, and returns a collection containing only items that satisfy an include condition.

We can get single object from this array of dictionary , you can use the following code

var dict = sortedArray.filter{($0["parentId"] as! String) == "compareId"}.first

OR

 let dict = sortedArray.filter{ ($0["parentId"] as! String) == "compareId" }.first
like image 50
IKKA Avatar answered Nov 01 '22 19:11

IKKA


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 }

like image 30
par Avatar answered Nov 01 '22 18:11

par