Массив фильтра [AnyObject] в Swift
У меня есть массив объектов AnyObject
в Swift. Каждый объект имеет атрибуты ресторана, такие как имя, тип, loc и т.д. Как фильтровать массив, если я хочу сохранить все объекты в массиве, которые содержат тип: "Sushi".
Пример массива [AnyObject]
с двумя объектами. Фильтр должен содержать первый объект (тип: суши):
[<Restaurant: 0x7ff302c8a4e0, objectId: LA74J92QDA, localId: (null)> {
City = "New York";
Country = "United States";
Name = Sumo Japan;
Type = Sushi, Japanese, Asian;
}, <Restaurant: 0x7ff302daa790, objectId: 0aKFrpKN46, localId: (null)> {
City = "New York";
Country = "United States";
Name = Little Italy;
Type = Italian, Pizza;
}]
Текущий код (но я не уверен, может ли фильтр выполнить поиск по массиву [AnyObject]
):
var query = PFQuery(className:"Restaurant")
query.whereKey("RestaurantLoc", nearGeoPoint:userGeoPoint, withinMiles:50)
query.limit = 2
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if objects != nil {
println("list of objects of nearby")
println(objects)
let searchString = "Sushi"
let predicate = NSPredicate(format: "Type CONTAINS[cd] %@", searchString);
//Line below gives error: '[AnyObject]' does not have a member named 'filteredArrayUsingPredicate'
//let filteredArray = objects.filteredArrayUsingPredicate(predicate!)
Ответы
Ответ 1
Ваш массив, objects
, представляет собой массив объектов PFObject
. Таким образом, к filter
массиву вы можете сделать что-то вроде:
let filteredArray = objects.filter() {
if let type = ($0 as PFObject)["Type"] as String {
return type.rangeOfString("Sushi") != nil
} else {
return false
}
}
Мой первоначальный ответ, основанный на предположении, что мы имеем дело с пользовательскими объектами Restaurant
, находится ниже:
Вы можете использовать метод filter
.
Предположим, что Restaurant
определяется следующим образом:
class Restaurant {
var city: String
var name: String
var country: String
var type: [String]!
init (city: String, name: String, country: String, type: [String]!) {
...
}
}
Итак, считая, что type
- это массив строк, вы бы сделали что-то вроде:
let filteredArray = objects.filter() {contains(($0 as Restaurant).type, "Sushi")}
Если ваш массив типов может быть nil
, вы можете выполнить его условное разворот:
let filteredArray = objects.filter() {
if let type = ($0 as Restaurant).type as [String]! {
return contains(type, "Sushi")
} else {
return false
}
}
Детали будут немного отличаться в зависимости от вашего объявления Restaurant
, которое вы не поделили с нами, но, надеюсь, это иллюстрирует идею.
Ответ 2
Хорошо, если массив объектов содержит только Ресторан (ы), следующий код работает.
Предположим, что ресторан выглядит примерно так:
enum RestaurantType {
case Sushi, Japanese, Asian
}
class Restaurant {
var type = [RestaurantType]()
// more properties here...
}
Прежде всего, определите массив ресторанов (ресторанов).
var restaurants = objects as [Restaurant]
Затем мы можем отфильтровать его:
var sushiRestaurants = restaurants.filter { (restaurant : Restaurant) -> Bool in
return contains(restaurant.type, .Sushi)
}
Update:
Теперь я предполагаю объекты - это массив PFObject (s)
Просто проигнорируйте мой предыдущий код и попробуйте следующее:
var restaurants = objects as [PFObject]
var sushiRestaurants = restaurants.filter { (restaurant : PFObject) -> Bool in
return contains(restaurant["Type"], "Sushi")
}
Возможно, он снова рухнет, проблема в том, что я не знаю тип Restaurant.Type. Я пытаюсь. Возможно, следующее сообщение об ошибке предоставит более полезную информацию.
Ответ 3
Модификация Rob ответит как Swift 2.0, в Swift 2.0 с использованием кода Rob выдает ошибку следующим образом -
initializer for conditional binding must have optional type, not 'string'
![введите описание изображения здесь]()
Однако это можно решить, используя инструкцию охраны вместо if-let, как показано ниже -
let filteredArray = objects.filter() {
guard let type = ($0 as PFObject)["Type"] as String else {
return false
}
return type.rangeOfString("Sushi") != nil
}
Ответ 4
Решение Swift 3
Используйте фильтр для массива.
let restaurants: [Restaurants] = [...]
restaurants.filter({(restaurant) in
return Bool(restaurant.type == "sushi")
})
или return Bool(restaurant.type.contains("sushi"))
, если тип - это массив.
Ответ 5
У меня есть решение, как указано ниже.
func filterByCuisineType(list: [Restaurant]) -> [Restaurant]{
if self.cuisineTypes.count == 0 {
return list
}
let array: [Restaurant] = list.filter { (restaurant) -> Bool in
for cuisineName in self.cuisineTypes{
let isContained: Bool = restaurant.cuisineType.contains(cuisineName)
if isContained {
return true
}
}
return false
}
return array
}