I have a NSMutableArray
which it self has many arrays inside it. Inside each array at all index they further had custom objects of class given bellow.
Class User:NSObject{
var name = ""
var userName = ""
var email = ""
var age = 0
var gender = ""
var
}
I want to filter this nested array with respect to two objects. For example if user type some text in searchBar and check that text in that nested array if that text matches with the name or the userName or both.
let nestedArray: [[User]] = [[user1, user2], [user3], [user4, user5]]
let searchName = "foo"
let filteredArray = nestedArray.map({
return $0.filter({ $0.name == searchName })
}).filter({ $0.count > 0 })
This is a purely functional way that results in a new nested array that only contains arrays with matching users and these arrays also will only contain the matching users.
A few suggestions
struct User {
let name: String
let userName: String
let email: String
let age: Int
let gender: String
}
NSMutableArray
is an Objective-C class. You can access it via Swift but you should use the Swift array struct. It is faster and, being a value type, prevents bugs related to multiple parts of your code accessing a shared object.
Now given an array of arrays of User
let data: [[User]] = ...
and a keyword
let keyword: String = ...
your can filter your data writing
let matchingUsers = data
.flatMap { $0 }
.filter { $0.name.range(of: keyword) != nil || $0.userName.range(of: keyword) != nil }
Now matchingUsers
is an array of User(s)
where the name
or the username
contains the keyword
.
let textToSearch:String = "some text"
for nestedArray in myArray {
for item:User in nestedArray
{
if user.name.contains(textToSearch) || user.userName.contains(textToSearch)
{
print("found")
}
}
}
Here is a more "swiftly" way to go about doing this using the filter(_:)
method provided by Array
.
Method:
func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> [Element]
Implementation:
// Create some generic objects to test on
let object1 = User()
object1.name = "John"
object1.userName = "jdoe"
let object2 = User()
object2.name = "Jane"
object2.userName = "jdoe"
let object3 = User()
object3.name = "Bob"
object3.userName = "bjones"
// Add them to a test array
var objects = [[]]
objects.append([object1])
objects.append([object2])
objects.append([object3])
// What we want to search on
let searchString = "j"
// Filter the array
for array in objects {
let searchedSubArray = array.filter {
return $0.name.rangeOfString(searchString, options: .CaseInsensitiveSearch) != nil ||
$0.userName.rangeOfString(searchString, options: .CaseInsensitiveSearch) != nil
}
if (searchedSubArray.count > 0) {
print("we found a match!")
}
}
A slightly improved version of what matteok suggested:
It makes sense to ignore register in such filtering, and instead of checking equality check if lookup target contains search query
Also using !$0.isEmpty
is more swifty than checking for $0.count > 0
let nestedArray: [[User]] = [[user1, user2], [user3], [user4, user5]]
let searchName = "foo".lowercased()
let filteredArray = nestedArray
.map { $0.filter { $0.name.lowercased().contains(searchName) }}
.filter { !$0.isEmpty }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.