How to Filter Nsarray in Swift

How to filter NSArray in Swift?

Here's what I ended up doing:

let resultPredicate = NSPredicate(format: "name contains[c] %@", searchText)
self.filteredUserData = self.userData.filteredArrayUsingPredicate(resultPredicate)

Objective-C version:

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];
self.filteredUserData = [self.userData filteredArrayUsingPredicate:resultPredicate];

How to filter an array using NSPredicate in swift 3

The native Swift equivalent to the ObjC code is

let filteredArray = arrayDirectory.filter { ($0["displayName2"] as! String).range(of: searchText!, options: [.diacriticInsensitive, .caseInsensitive]) != nil }

assuming arrayDirectory is a native Swift Array. It considers also the case insensitive and diacritic insensitive parameters.

How to filter NSArray using predicate on an object property

Try following lines, and make sure properyName is case sensitive. and you have placed , in predicate format, thats why its not working. just replace your code with following.

Objective C

NSPredicate *bPredicate = [NSPredicate predicateWithFormat:@"SELF.name contains[cd] %@",self.searchText.text];
self.filteredArray = [self.hotelArray filteredArrayUsingPredicate:bPredicate];
NSLog(@"HERE %@",self.filteredArray);

Swift

var bPredicate: NSPredicate = NSPredicate(format: "SELF.name contains[cd] %@", self.searchText.text)
self.filteredArray = self.hotelArray.filteredArrayUsingPredicate(bPredicate)
NSLog("HERE %@", self.filteredArray)

Using swift filter

var searchText = "Galaxy"

let filteredArray = hotelArray.filter { $0["name"] == searchText }
print("** Result ** \n\(filteredArray)")

Swift 3.0

let arrEmp = [["name": "James", "age" : 27, "city" : "New york"],
["name": "Johnson", "age" : 24, "city" : "London"],
["name": "Alex", "age" : 28, "city" : "Newark"],
["name": "Mark", "age" : 25, "city" : "Paris"],
["name": "Steve", "age" : 25, "city" : "Silicon Valley"],
["name": "Lary", "age" : 28, "city" : "New york"]]

// *** Filter by Name exact match ***
var filterByName = arrEmp.filter { $0["name"] == "Mark" }
print("filterByName \(filterByName)")

// *** Filter by Age ***
var filterByAge = arrEmp.filter { $0["age"] as! Int > 25 }
print("filterByAge \(filterByAge)")

Swift 4.0

var filterByName = arrEmp.filter
do {
$0["name"] == "Mark"
}
print("filterByName filterByName)")

var filterByAge = arrEmp.filter
do {
$0["age"] as! Int > 25
}
print("filterByAge filterByAge)")

I filtered an NSMutableArray of Dictionaries and then I want to filter for a Key again

  1. Don't use NSArray or NSMutableArray in Swift. Use Swift native arrays (and dictionaries).
  2. Once you do that, there is no need for NSPredicate. Use the filter method.
  3. Don't use a dictionary to hold your data. Create a struct with the needed fields.

First, without creating a struct, here's a simply solution using native arrays:

var dataArray = [[String:Any]]()
var sum = 0.00

func addNewIncomeRecord(_ id: String, date: String, description: String, amount: Double, currency: String, category: String, notes: String) {
let dict: [String:Any] = ["id" : id, "date" : date, "description" : description, "amount" : amount, "currency" : currency, "category" : category, "notes" : notes]

dataArray.append(dict)
}

addNewIncomeRecord("1", date: "11-25", description: "Money", amount: 20.00, currency: "EUR", category: "Home", notes: "More Money")
addNewIncomeRecord("2", date: "11-25", description: "Rent", amount: 50.00, currency: "EUR", category: "Home", notes: "Rent Money")
addNewIncomeRecord("3", date: "11-25", description: "Hair", amount: 10.00, currency: "EUR", category: "Medical" ,notes: "HairCut")

let filteredArray = dataArray.filter { $0["category"] as? String == "Home" }
let amounts = filteredArray.flatMap { $0["amount"] as? Double }
print(amounts)

Here's the solution making use of a struct.

struct Income {
let id: String
let date: String
let description: String
let amount: Double
let currency: String
let category: String
let notes: String
}

var dataArray = [Income]()
var sum = 0.00

func addNewIncomeRecord(_ id: String, date: String, description: String, amount: Double, currency: String, category: String, notes: String) {
let income = Income(id: id, date: date, description: description, amount: amount, currency: currency, category: category, notes: notes)

dataArray.append(income)
}

addNewIncomeRecord("1", date: "11-25", description: "Money", amount: 20.00, currency: "EUR", category: "Home", notes: "More Money")
addNewIncomeRecord("2", date: "11-25", description: "Rent", amount: 50.00, currency: "EUR", category: "Home", notes: "Rent Money")
addNewIncomeRecord("3", date: "11-25", description: "Hair", amount: 10.00, currency: "EUR", category: "Medical" ,notes: "HairCut")

let filteredArray = dataArray.filter { $0.category == "Home" }
let amounts = filteredArray.map { $0.amount }
print(amounts)

Using a struct has many advantages. It's type safe for each field. You can make it Codable which makes it a lot easier to save and read from a file.

Filter NSArray based on another array using predicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]];
NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate];

complete example

@interface Alpha : NSObject
@property (nonatomic, copy) NSString *username;
-(instancetype) initWithUsername:(NSString *)username;
@end

@implementation Alpha
-(instancetype) initWithUsername:(NSString *)username
{
self = [super init];
if (self) {
self.username = username;
}
return self;
}

-(NSString *)description{
return [NSString stringWithFormat:@"%@: %@", NSStringFromClass([self class]), self.username];
}
@end

NSArray *all_usernames = @[[[Alpha alloc] initWithUsername:@"a"], [[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"z"], [[Alpha alloc] initWithUsername:@"f"], [[Alpha alloc] initWithUsername:@"e"]];
NSArray *some_usernames = @[[[Alpha alloc] initWithUsername:@"b"], [[Alpha alloc] initWithUsername:@"f"]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (self.username IN %@)", [some_usernames valueForKey:@"username"]];
NSArray *remaining_usernames = [all_usernames filteredArrayUsingPredicate:predicate];

NSLog(@"%@", remaining_usernames);

prints

(
"Alpha: a",
"Alpha: z",
"Alpha: e"
)

Search in NSMutableArray

Instead of extracting and filtering the "name" values you can filter the array directly, using the corresponding key path instead of “SELF” in the predicate:

let array = NSArray(array: [
["id": 1, "name": "x1"], ["id": 2, "name": "x2"], ["id": 3, "name": "y3"]])

let predicate = NSPredicate(format: "name BEGINSWITH [c] %@", "x")
let filtered = array.filtered(using: predicate)

print(filtered)

Result:

[{
id = 1;
name = x1;
}, {
id = 2;
name = x2;
}]

Another option is to cast the NS(Mutable)Array to a Swift array of dictionaries, and use the filter() function:

if let a = array as? [[String: Any]] {
let filtered = a.filter {
($0["name"] as? String)?
.range(of: "x", options: [.caseInsensitive, .anchored]) != nil
}
print(filtered)
// [["id": 1, "name": x1], ["name": x2, "id": 2]]
}

filtering NSArray into a new NSArray in Objective-C

NSArray and NSMutableArray provide methods to filter array contents. NSArray provides filteredArrayUsingPredicate: which returns a new array containing objects in the receiver that match the specified predicate. NSMutableArray adds filterUsingPredicate: which evaluates the receiver’s content against the specified predicate and leaves only objects that match. These methods are illustrated in the following example.

NSMutableArray *array =
[NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil];

NSPredicate *bPredicate =
[NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB =
[array filteredArrayUsingPredicate:bPredicate];
// beginWithB contains { @"Bill", @"Ben" }.

NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:@"SELF contains[c] 's'"];
[array filteredArrayUsingPredicate:sPredicate];
// array now contains { @"Chris", @"Melissa" }


Related Topics



Leave a reply



Submit