web-dev-qa-db-fra.com

Filtrer le tableau de [AnyObject] dans Swift

J'ai un tableau d'objets AnyObject dans Swift. Chaque objet a des attributs d'un restaurant, tels que le nom, le type, le lieu, etc. Comment puis-je filtrer le tableau si je veux conserver tous les objets du tableau qui contiennent le type: "Sushi".

Exemple de tableau de [AnyObject] avec 2 objets. Le filtre doit conserver le premier objet (type: sushi):

[<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;
}]

Code actuel (mais je ne sais pas si le filtre peut rechercher dans un tableau de [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!)
26
Onichan

Votre tableau, objects, est un tableau d'objets PFObject. Ainsi, pour filter le tableau, vous pourriez faire quelque chose comme:

let filteredArray = objects.filter() {
    if let type = ($0 as PFObject)["Type"] as String {
        return type.rangeOfString("Sushi") != nil
    } else {
        return false
    }
}

Ma réponse originale, basée sur l'hypothèse que nous avions affaire à des objets Restaurant personnalisés, est ci-dessous:


Vous pouvez utiliser la méthode filter.

Supposons que Restaurant soit défini comme suit:

class Restaurant {
    var city: String
    var name: String
    var country: String
    var type: [String]!

    init (city: String, name: String, country: String, type: [String]!) {
        ...
    }
}

Donc, en supposant que type est un tableau de chaînes, vous feriez quelque chose comme:

let filteredArray = objects.filter() {contains(($0 as Restaurant).type, "Sushi")}

Si votre tableau de types pouvait être nil, vous en feriez un déballage conditionnel:

let filteredArray = objects.filter() {
    if let type = ($0 as Restaurant).type as [String]! {
        return contains(type, "Sushi")
    } else {
        return false
    }
}

Les détails varieront un peu selon votre déclaration de Restaurant, que vous n'avez pas partagée avec nous, mais j'espère que cela illustre l'idée.

54
Rob

Ok, si le tableau objets ne contient que Restaurant (s) le code suivant fonctionne.

Disons que le restaurant est quelque chose comme ça:

enum RestaurantType {
    case Sushi, Japanese, Asian
}

class Restaurant {
    var type = [RestaurantType]()
    // more properties here...
}

Tout d'abord, définissons un tableau de restaurant (s).

var restaurants = objects as [Restaurant]

Ensuite, nous pouvons le filtrer:

var sushiRestaurants = restaurants.filter { (restaurant : Restaurant) -> Bool in
    return contains(restaurant.type, .Sushi)
}

Mise à jour: Maintenant, je suppose que objets est un tableau de PFObject (s) Ignorez simplement mon code précédent et essayez ceci:

var restaurants = objects as [PFObject]
var sushiRestaurants = restaurants.filter { (restaurant : PFObject) -> Bool in
    return contains(restaurant["Type"], "Sushi")
}

Peut-être que ça va planter à nouveau, le problème est que je ne connais pas le type de Restaurant.Type. J'essaie. Peut-être que le prochain message d'erreur fournira des informations plus utiles.

8
Luca Angeletti

Solution Swift 3

Utilisez la méthode de filtrage sur un tableau.

let restaurants: [Restaurants] = [...]
restaurants.filter({(restaurant) in
    return Bool(restaurant.type == "sushi")
})

ou return Bool(restaurant.type.contains("sushi")) si type est un tableau.

8
Derek Soike

La modification de la réponse de Rob comme Swift 2.0, In Swift 2.0 utilisant le code de Rob donne l'erreur comme suit -

initializer for conditional binding must have optional type, not 'string'

enter image description here

Cependant, il peut être résolu en utilisant la déclaration de garde au lieu de if-let comme ci-dessous -

let filteredArray = objects.filter() {
            guard let type = ($0 as PFObject)["Type"] as String else {
                return false
            } 
            return type.rangeOfString("Sushi") != nil
        }
5
AppsWise

J'ai une solution comme indiqué ci-dessous.

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
}
3
Coder_A_D