Reputation: 11175
I have some code that searches through one of my arrays, and it works great, however I would now like to modify it slightly.
Basically, at the moment it searches through a list of attractions by their name. I would like to change this so that it searches through by name, but not the entire name, just if it contains the search string.
This is my current code:
func getRideByName(name: String) -> Ride? {
//Returns ride by name or nil if not found
let result = self.rideArray.filter({
$0.name == name
})
return result.count == 0 ? nil : result[0]
}
How can I change this code to find attraction names that contain the search string?
EDIT
Here is how the contents of the rideArray
:
class Ride: NSObject {
var name: String?
var waitTime: String?
var longitude: Double?
var latitude: Double?
var updated: NSDate?
var fastPass: Bool?
var disabledAccess: Bool?
var singleRider: Bool?
var heightRestriction: Bool?
var rideDescription: String?
var hasWaitTime: Bool?
var rideImage: String?
var rideImageSmall: String?
var mustSee: Bool?
var isLive: Bool?
init(name: String?, waitTime: String?, longitude: Double?, latitude: Double?, updated: NSDate?, fastPass: Bool?, disabledAccess: Bool?, singleRider: Bool?, heightRestriction: Bool?, rideDescription: String?, hasWaitTime: Bool?, rideImage: String?, rideImageSmall: String?, mustSee: Bool?, isLive: Bool?) {
self.name = name
self.waitTime = waitTime
self.longitude = longitude
self.latitude = latitude
self.updated = updated
self.fastPass = fastPass
self.disabledAccess = disabledAccess
self.singleRider = singleRider
self.heightRestriction = heightRestriction
self.rideDescription = rideDescription
self.hasWaitTime = hasWaitTime
self.rideImage = rideImage
self.rideImageSmall = rideImageSmall
self.mustSee = mustSee
self.isLive = isLive
}
}
for object in objects {
var ride = Ride(
name: object.objectForKey("Name") as? String,
waitTime: object.objectForKey("WaitTime") as? String,
longitude: object.objectForKey("Longitude") as? Double,
latitude: object.objectForKey("Latitude") as? Double,
updated: object.updatedAt as NSDate?,
fastPass: object.objectForKey("FastPass") as? Bool,
disabledAccess: object.objectForKey("DisabledAccess") as? Bool,
singleRider: object.objectForKey("SingleRider") as? Bool,
heightRestriction: object.objectForKey("HeightRestriction") as? Bool,
rideDescription: object.objectForKey("RideDescription") as? String,
hasWaitTime: object.objectForKey("HasWaitTime") as? Bool,
rideImage:(object.objectForKey("RideImage") as? PFFile)?.url,
rideImageSmall:(object.objectForKey("RideImageSmall") as? PFFile)?.url,
mustSee: object.objectForKey("MustSee") as? Bool,
isLive: false)
self.rideArray.append(ride)
}
Upvotes: 0
Views: 54
Reputation: 59506
Looking at your code it looks that:
let rideArray : [Ride]
(maybe var
but does not matter now).
I also see that Ride
is a class
or a struct
having a property name
of type String?
.
struct Ride {
let name: String?
}
Finally your class has e property named rideArray
of type [Ride]
.
class Foo {
let rideArray : [Ride]
}
class Foo {
let rideArray : [Ride] = [Ride(name: "one"), Ride(name: "two"), Ride(name: "three")]
// Important: there is a much better implementation of this method at the end of this answer
func getRideByName(name: String) -> Ride? {
return rideArray.filter { $0.name?.rangeOfString(name) != nil }.first
}
}
Foo().getRideByName("one") // {name "one"}
Foo().getRideByName("on") // {name "one"}
Foo().getRideByName("o") // {name "one"}
Foo().getRideByName("wrong") // nil
Foo().getRideByName("the") // {name "three"}
Hope this helps.
In the comment below, user Qbyte suggested to use indexOf
instead of filter
inside the getRideByName
method for performance improvements reasons.
Qbyte is totally right.
Infact my initial implementation was iterating all the elements in rideArray
(even when the matching element was the first one!). This was an unnecessary waste of resources and time.
Instead it is a plausible assumption that the indexOf
method does iterate until the matching element is found. No more.
From Official Documentation of indexOf
:
Returns the first index where predicate returns true for the corresponding value, or nil if such value is not found.
This is a much better implementation of getRideByName
and you should use this.
func getRideByName(name: String) -> Ride? {
if let index = ( rideArray.indexOf { return $0.name?.rangeOfString(name) != nil}) {
return rideArray[index]
}
return nil
}
Upvotes: 2
Reputation: 1300
To check if a string is a substring of another string, you could use the containsString
method:
func getRideByName(name: String) -> Ride? {
//Returns ride by name or nil if not found
let result = self.rideArray.filter({
$0.name.containsString(name)
})
return result.count == 0 ? nil : result[0]
}
Upvotes: 0