0

I have an array called master and it is of type Array<Dictionary<String, String>>(). I am trying to use the filter function, like this:

filteredMusic = allSongNames.filter({ (song: String) -> Bool in
    let stringMatch = song.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
    return stringMatch != nil
})

Where filteredMusic and allSongNames are both arrays of String. I try to translate this with my master array, and masterFilter (same type as master):

masterFilter = master.filter({ (song: String, id: String) -> Bool in
    let stringMatch = song.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
    return stringMatch != nil
})

My error:

'(String, String) -> Bool' is not convertible to '([String : String]) -> Bool'

I must be messing up syntax. What is the correct syntax?

1
  • Your desired result is... an array of dictionaries of (song,id) where one entry in the dictionary has the desired searchText? That does't sound very useful. I'd think that you want an array of (song,id)?? Commented Aug 29, 2015 at 0:01

2 Answers 2

1

In your filter's closure, you're accepting two String parameters, but you must accept a single [String:String] instead (i.e, the type that your array contains: Dictionary<String, String>). Therefore, you need to change your filter to something like…

masterFilter = master.filter({ (dictionary: [String:String]) -> Bool in
    …
})

Because your filter is now accepting a dictionary instead of two strings, you need to change how it works. Presumably you'll want to iterate through the dictionary performing a search, but the exact implementation depends on what you're trying to acheive. An example might be:

masterFilter = master.filter({ (dictionary: [String:String]) -> Bool in
    for (song, id) in dictionary {
        if song.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil {
            return true
        }
    }

    return false
})
Sign up to request clarification or add additional context in comments.

Comments

0

The type signature of Array's filter instance method is

func filter(includeElement: (T) -> Bool) -> [T]

Which means that it takes a function that takes an argument of type T and returns true or false and the filter instance methods returns an array of type T which is the same type as the function's parameter given to it.

Your first use of filter works because it's an array of String data types though the second doesn't work because (song: String, id: String) implies that there's a function with two parameters given to filter. The error generated by compiler fully describes it. It says the type is a dictionary thus [String : String]. So, in order to make it work you should do it in this way:

Remember that Dictionary data type has an instance variable called keys which returns a value of type LazyForwardCollection<MapCollectionView<[Key : Value], Key>>. The definition is

var keys: LazyForwardCollection<MapCollectionView<[Key : Value], Key>> { get }

LazyForwardCollection has an instance variable first which gives you the first element, it also has array which gives you all the elements.

var first: S.Generator.Element? { get }

// Let the compiler infer the type though you can give (dict: [String : String]) -> Bool
masterFilter = master.filter { dict in 
        let song = dict.keys.first

        let stringMatch = song.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
        return stringMatch != nil
    }

I didn't use for-in loop because the way your code showed(though it didn't compile) me, it just has one key/value pair in dictionaries inside the array. Although you can use it if there's a need.

You also didn't use id. So it seems to me that you don't need the values, though the nature of dictionary is that you need both keys and values otherwise Array data type would work. One possible guess is that you're retrieving the data from a web server that returns a JSON or other notations so you first cast it to dictionary then use it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.