Filtering array of custom objects
From what I can see from your question, none of the above really has any connection to Objective-C. Your example contains a few other issues, however, keeping it from working as intended.
MyObject
has no initializer (as of Swift 2.2, you should include at least one initializer).- What are
obj1
,obj2
, ... ? You treat these as methods or class/structures types, when I presume you're intending for these to be instances of theMyObject
type.
If fixing the above, the actual filtering part of your code will work as intended (note that you can omit ()
from filter() {... }
), e.g.:
enum ObjectType{
case type1
case type2
case type3
}
class MyObject {
var type : ObjectType
let id: Int
init(type: ObjectType, id: Int) {
self.type = type
self.id = id
}
}
let array = [MyObject(type: .type1, id: 1),
MyObject(type: .type2, id: 2),
MyObject(type: .type3, id: 3),
MyObject(type: .type2, id: 4),
MyObject(type: .type3, id: 5)]
let type2Array = array.filter { $0.type == .type2}
type2Array.forEach { print($0.id) } // 2, 4
As an alternative to filtering directly to an enumeration case, you could specify the rawValue
type of your enumeration and match to this instead. E.g. using an Int
rawValue
allows you to (in addition to filtering w.r.t. rawValue
) perform pattern matching for say, ranges of cases in your enumeration.
enum ObjectType : Int {
case type1 = 1 // rawValue = 1
case type2 // rawValue = 2, implicitly
case type3 // ...
}
class MyObject {
var type : ObjectType
let id: Int
init(type: ObjectType, id: Int) {
self.type = type
self.id = id
}
}
let array = [MyObject(type: .type1, id: 1),
MyObject(type: .type2, id: 2),
MyObject(type: .type3, id: 3),
MyObject(type: .type2, id: 4),
MyObject(type: .type3, id: 5)]
/* filter w.r.t. to rawValue */
let type2Array = array.filter { $0.type.rawValue == 2}
type2Array.forEach { print($0.id) } // 2, 4
/* filter using pattern matching, for rawValues in range [1,2],
<=> filter true for cases .type1 and .type2 */
let type1or2Array = array.filter { 1...2 ~= $0.type.rawValue }
type1or2Array.forEach { print($0.id) } // 1, 2, 4
How do I filter on an array of objects in Swift?
So I quickly did this to help out, if someone can improve that's fine I'm just trying to help.
I made a struct for the books
struct Book {
let title: String
let tag: [String]
}
Created an array of those
var books: [Book] = []
Which is empty.
I created a new object for each book and appended to books
let dv = Book(title: "The Da Vinci Code", tag: ["Religion","Mystery", "Europe"])
books.append(dv)
let gdt = Book(title: "The Girl With the Dragon Tatoo", tag: ["Psychology","Mystery", "Thriller"])
books.append(gdt)
let fn = Book(title: "Freakonomics", tag: ["Economics","non-fiction", "Psychology"])
books.append(fn)
So you've three objects in the books array now.
Try to check with
print (books.count)
Now you want to filter for Psychology books.
I filtered the array for tags of Psychology - are filters ok for you?
let filtered = books.filter{ $0.tag.contains("Psychology") }
filtered.forEach { print($0) }
Which prints the objects with your two Psychology books
Book(title: "The Girl With the Dragon Tatoo", tag: ["Psychology",
"Mystery", "Thriller"])Book(title: "Freakonomics", tag: ["Economics", "non-fiction",
"Psychology"])
Filter Nested Array of Custom Object in Swift
I believe it is possible to achieve your goal using your approach and simply adapting your filter logic.
Try creating a method to filter your array of SectionIndex
instances:
let array: [SectionIndex] = []
The method loops through each section and filters the rows the same way you did. After that, simply verify if any row matched the search and if it did, create a new SectionIndex
copy adding only the rows that matched the search.
func filterSections(with searchText: String) -> [SectionIndex] {
var searchedData: [SectionIndex] = []
for sectionIndex in array {
let filteredRows: [RowIndex] = sectionIndex.data.filter({
$0.reg?.range(of: searchText, options: [.caseInsensitive, .diacriticInsensitive]) != nil
|| $0.type?.range(of: searchText, options: [.caseInsensitive, .diacriticInsensitive]) != nil
|| $0.type?.removingSymbols().range(of: searchText, options: [.caseInsensitive, .diacriticInsensitive]) != nil
|| $0.reg?.removingSymbols().range(of: searchText, options: [.caseInsensitive, .diacriticInsensitive]) != nil
})
// Ignore the section if not rows match the search
if filteredRows.isEmpty { continue }
let newSectionIndex = SectionIndex(
index: sectionIndex.index!, // TODO: handle the optional value
title: sectionIndex.title!, // TODO: handle the optional value
date: sectionIndex.date!, // TODO: handle the optional value
data: filteredRows,
minutes: sectionIndex.minutes! // TODO: handle the optional value
)
searchedData.append(newSectionIndex)
}
return searchedData
}
Finally on the search callback:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
{
if searchText != ""
{
searchedData = filterSections(with: searchText)
searching = true
table1.reloadData()
}
else
{
searching = false
table1.reloadData()
}
}
The tableView
data source methods would look like something like this:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchedData[section].data.count
} else {
return array[section].data.count
}
}
func numberOfSections(in tableView: UITableView) -> Int {
if searching {
return searchedData.count
} else {
return array.count
}
}
Filter array of custom objects with an attribute and Map in Swift
for (index, job) in idsJobModel.enumerated() {
if let match = arrFiltetered.first( where: {job.id == $0.id} ) {
idsJobModel[index] = match
}
}
Or if you prefer using map:
idsJobModel = idsJobModel.map {
let myID = $0.id
if let match = arrFiltetered.first( where: {myID == $0.id} ) {
return match
} else {
return $0
}
}
Either version of the code above will have O(n²)
performance, so it will get dramatically slower as your arrays get larger than ≈30 elements. It would need to be tweaked to perform well on larger arrays.
How Filter Custom Object Array with Condition
let result = secondArray
result.append(contentsOf: fisrtArray.filter { item in
!secondArray.contains(where: { $0.id == item.id })
})
After that you can sort the result
by id
Swift: Get indices of an array of objects filtered by a certain property
You could filter the indices
let selectedIndices = myObjects.indices.filter{selectedIds.contains(myObjects[$0].ID)}
Filter array of custom objects in Swift
In Swift 1.2, filter
is a global function, so you can't say dataPool.filter(...)
. (In Swift 2, this will work.)
Furthermore, contains
can't be used with Strings like that. I would recommend using the rangeOfString:
method from NSString:
let teachers = filter(dataPool) { // in Swift 2 this would be "dataPool.filter {"
return $0.position!.rangeOfString("TEACHER") != nil
}
How to filter array of items by another array of items in swift
Chose 1 in 2 option of return:
func filter(items: [Item], contains tags: [String]) -> [Item] {
items.filter { (item) -> Bool in
let tagNames = item.tags.map({ $0.name })
return tags.allSatisfy(tagNames.contains)
return Set(tags).isSubset(of: Set(tagNames))
}
}
Related Topics
How to Deal with Non-Optional Values in Nsuserdefaults in Swift
Get Path to Subdirectory in Resources Folder
How to Animate Uilabel's Textcolor Change
iOS UIlabel Autoshrink So Word Doesn't Truncate to Two Lines
Collide Type Source Error - Spritekit Swift Game
Notification in Swift Every Day at a Set Time
Auto Layout How to Hide 1 View in a View with 3 Equal Width Views
Default Uifont Size and Weight But Also Support Preferredfontfortextstyle
How to Make a Phonegap App for iOS Without Mac
How to Add a Lock Screen Widget (Requiring iOS 16) and Still Support iOS 15
Random Glitchy Rendering of Svg on iOS/Wkwebview
Bootstrap Columns with Flexbox Are Not Taking Proper Width on iOS and Safari
How to Set Requestserializer in Alamofire
How to Print Name of The Day of The Week
Mkannotation Not Getting Selected in iOS5
Calculate The Range of Visible Text in UIlabel
How to Get Index of Xcuielement in Xcuielementquery
Initialization of 'Unsafepointer<Int>' Results in a Dangling Pointer