Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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 = ""
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.
Don't use NSMutableArray
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.
Filtering your data
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
.
–
–
for item:User in nestedArray
if user.name.contains(textToSearch) || user.userName.contains(textToSearch)
print("found")
–
–
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 }
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!")
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.