Подтвердить что ты не робот

Массив фильтра [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!)
4b9b3361

Ответ 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
}