Filter content for search text with lowercased and array

I have struct with cities: [String] in firestore

struct CityList {
    var country: String
    var cities: [String]
}

Struct in firestore looks like on

1
    country: Russia
    cities: ["Moscow", "Saint-Petersburg"]
2
    country: USA
    cities: ["New York", "Los Angeles"]

I need to use filter array of strings cities: [String] when I use searchController. Now I have func filterContentForSearchText

private func filterContentForSearchText(_ searchText: String) {
    filteredCityList = cityList.filter({ (cityList: CityList) -> Bool in
        return cityList.cities[0].lowercased().contains(searchText.lowercased())
    })
    tableView.reloadData()
}

I know with my mistake is -> cities[0], but I don't understand how to fix it...

And when I write text in searchController, searchController search only first city it's Moscow or New York.

How I can search Moscow, Saint-Petersburg, New York and Los Angeles?

Upvotes: 0

Views: 403

Answers (3)

Moris Kramer
Moris Kramer

Reputation: 1560

You trying to filter on Struct, it won't work. Try using filter on Array of cities instead.


I think your data structure can be improved like this:

let searchText = "Moscow"

 // for easch Country: Cities array
let worldCities: [String: [String]] = [ "Russia": ["Moscow", "Saint-Petersburg"],
                                        "USA": ["New York", "Los Angeles"]
                                        ]


let result = worldCities["Russia"]?.filter({ city -> Bool in
    if city.lowercased().contains(searchText.lowercased()) {
        return true
    } else {
        return false
    }
})

In case you want go over all countries, you should probably use single array of all cities or merge with above example:

let all = worldCities.values

Upvotes: 0

Casper Zandbergen
Casper Zandbergen

Reputation: 3687

So your cities[0] only takes the first city, I assume you need to search in all cities so I would check cities.contains. I would also use localizedCaseInsensitiveContains instead of manually lowercasing.

cities.contains {
    $0.localizedCaseInsensitiveContains(searchText)
}

the filter would be:

cityList.filter { list in
    list.cities.contains { city in
        city.localizedCaseInsensitiveContains(searchText)
    }
}

Upvotes: 3

Khushbu
Khushbu

Reputation: 2430

let arrayFiltered = CityList.cities.filter{
       $0.lowercased().contains(searchText.lowercased())
}

Please try this.

Upvotes: 0

Related Questions