SwiftにはAnyObject
オブジェクトの配列があります。各オブジェクトには、名前、タイプ、場所などのレストランの属性があります。タイプ「寿司」を含む配列内のすべてのオブジェクトを保持する場合、配列をフィルター処理するにはどうすればよいですか。
2つのオブジェクトを含む[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!)
配列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
の宣言に応じて少し異なりますが、これは私たちとは共有していませんが、うまくいけばこの考えを示しています。
配列objectsにRestaurant(s)次のコードは機能します。
Restaurantは次のようなものだとしましょう。
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)
}
更新:今私はobjectsがPFObject(s)の配列であると仮定しています。以前のコードを無視してこれを試してください:
var restaurants = objects as [PFObject]
var sushiRestaurants = restaurants.filter { (restaurant : PFObject) -> Bool in
return contains(restaurant["Type"], "Sushi")
}
おそらく再びクラッシュするかもしれませんが、問題はRestaurant.Typeのタイプがわからないことです。私はしようとしています。次のエラーメッセージでもっと役立つ情報が得られるかもしれません。
Swift 3ソリューション
配列で filter method を使用します。
_let restaurants: [Restaurants] = [...]
restaurants.filter({(restaurant) in
return Bool(restaurant.type == "sushi")
})
_
またはreturn Bool(restaurant.type.contains("sushi"))
typeが配列の場合。
Swift 2.0、In Swift 2.0としてRobのコードを使用すると、次のようなエラーが発生します-
initializer for conditional binding must have optional type, not 'string'
ただし、以下のようにif-letの代わりにguardステートメントを使用することで解決できます-
let filteredArray = objects.filter() {
guard let type = ($0 as PFObject)["Type"] as String else {
return false
}
return type.rangeOfString("Sushi") != nil
}
以下に示すような解決策があります。
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
}