Reputation: 79
This is my first post, and I am very happy to join in this community. I am learning Swift with Ray Wenderlich's video tutorial. The challenge I got for lesson 3 is remove a element in an array without hard-coding the index. I understand the correct answer that Ray provided, but just don't understand why my answer can not work. Please see following for Ray's answer as well as my answer. If anyone can explain it for me, that would be great!! thanks:]
Correct Answer:
// Make an array with "C", "C++", and "Objective-C"
var programmingLanguages = ["C", "C++", "Objective-C"]
// Append "Swift" to the array
programmingLanguages += "Swift"
// Insert "Javascript" at Index 2
programmingLanguages.insert("Javscript", atIndex: 2)
// Remove "Objective-C" (without hard-coding the index)
let optIndex = find(programmingLanguages, "Objective-C")
if let defIndex = optIndex {
programmingLanguages.removeAtIndex(defIndex)
}
programmingLanguages
My answer1:
// Make an array with "C", "C++", and "Objective-C"
var programmingLanguages = ["C", "C++", "Objective-C"]
// Append "Swift" to the array
programmingLanguages += "Swift"
// Insert "Javascript" at Index 2
programmingLanguages.insert("Javscript", atIndex: 2)
// Remove "Objective-C" (without hard-coding the index)
programmingLanguages.removeAtIndex(find(programmingLanguages,"Objective-C")
programmingLanguages
My answer2:
// Make an array with "C", "C++", and "Objective-C"
var programmingLanguages = ["C", "C++", "Objective-C"]
// Append "Swift" to the array
programmingLanguages += "Swift"
// Insert "Javascript" at Index 2
programmingLanguages.insert("Javscript", atIndex: 2)
// Remove "Objective-C" (without hard-coding the index)
let optIndex = find(programmingLanguages, "Objective-C")
programmingLanguages.removeAtIndex(optIndex)
programmingLanguages
Upvotes: 3
Views: 1137
Reputation: 864
While I think Jiaaro nails it brevity-wise, here's a function I wrote today that does something similar. I didn't know about the find
function and while longer, it's easy to follow and might help you get the concept.
func arrayByRemovingObjectIdenticalTo<T: Equatable>(objectToRemove: T, fromArray:[T]) -> [T] {
var returnArray = fromArray
for (index, object) in enumerate(fromArray) {
if object == objectToRemove {
returnArray.removeAtIndex(index)
}
}
return returnArray
}
Upvotes: 0
Reputation: 76898
When you use find()
it is not guaranteed to return a result (what happens here?: find(programmingLanguages, "rick astley")
)
To account for this possibility find()
returns an "optional" - which basically just means that when it does not find a match it will return nil
.
In order to protect you from accidentally using nil
in some place that does not know how to handle it, the language considers optionals to be a distinct type. In short, you must check for nil when you get an optional value.
The main way to do that is with "if let" syntax – as seen in Ray's example – but a more terse (and more common) way to do it is like so:
if let defIndex = find(programmingLanguages, "Objective-C") {
programmingLanguages.removeAtIndex(defIndex)
}
if you know for sure that the optional is not nil
(like if you are checking for something you just inserted) you can use "forced unwrapping" which grabs the value out of the optional (and will cause an error and crash if it's nil
).
You do forced unwrapping using the forced unwrapping operator, the exclamation point !
:
// defIndex is an optional
let defIndex = find(programmingLanguages, "Objective-C")
// defIndex! <-- unwraps the optional but raises an error if it's nil
programmingLanguages.removeAtIndex(defIndex!)
Upvotes: 7
Reputation: 41226
Your answer doesn't work because find returns an optional value (the type is Int?
and not Int
), primarily so that if the the value is not found, it returns nil
, if the value is found it returns the index wrapped in an optional value. Your answer then attempts to pass that optional value to removeAtIndex
, which takes a Int
parameter, not an Int?
.
Ray's answer conditionally unwraps the result and checks it's validity before attempting to pass it on to removeAtIndex.
Upvotes: 0