The general question of why the following code fails has been answered already. But my question is, if it's never possible, why isn't this a compiler error?
Here's a minimal example: I can define this function and the compiler doesn't complain even though the unsafeBitCast will always fail:
func foo() -> [Int] {
let arr: [Int?] = [1, 2, 3, 4]
guard let barr = arr as? [Int] else { return [] }
return barr
}
This doesn't fail until we actually try to call foo() at runtime.
It is a compiler bug, because [Int] is not subtype of [Int?] So, your code shouldn't compile without any error. However, next code should work as expected
let i: [Int?] = [1,2,3]
let d: [Double?] = [1,2,3]
func foo<T>(arr:[T?]?) -> [T] {
guard let barr = arr where T.self == Int.self else { return [] }
return barr.flatMap{ $0 }
}
print(foo(i), foo(i).dynamicType)
print(foo(d), foo(d).dynamicType)
/*
[1, 2, 3] Array<Int>
[] Array<Double>
*/
Please, fill the bug report! More interestingly next code doesn't compile
let j = [Optional(1),Optional(2)] as? [Int]
but
let j = [Optional(1),Optional(2)]
let k = j as? [Int]
compile and crash ...
let arr0:[Int?]? = [1,2,3]
if let r = arr0 where r.dynamicType == [Int].self {
print(r, r.dynamicType)
} else {
print("not [Int]")
}
// prints
// not [Int]
// but
func foo()->[Int] {
let arr0:[Int?]? = [1,2,3]
if let r = arr0 where r.dynamicType == [Int].self {
print(r, r.dynamicType)
// !!!!! ERROR !!!!!
// next line doesn't compile wihout flatMap !!!!
//
// error: cannot convert return expression of type '[Int?]' to return type '[Int]'
//
// even though that it is clear from the where clause that r type must be [Int]
return r.flatMap{ $0 }
} else {
print("arr0 is not [Int]")
return []
}
}
foo() // [] and prints: arr0 is not [Int]
Related
I have an array of digits presented like strings - ["1", "2", "3"]
my goal is to return back the multiplied array.
func multiplyInts(_ num: Int) -> Array<Any> {
var arr = Array(String(num))
var resultArr = [Int]()
for i in 0...arr.count {
var strIn = String(arr[i])
var numIn = Int(strIn) * 2 // here's the error
resultArr.append(numIn)
}
return Array(resultArr)
}
I'm converting String to Int and multiplying this number by two, but my program won't compile and says error.
Basically there are at least two displayed errors and a fatal mistake.
The return type is wrong
Int(strIn) returns an optional, you have to (safely) unwrap it
0...arr.count will cause a crash, it must be 0..<arr.count
Further
the parameter type should be [String]
Creating an Array from an Array is redundant.
Long story short: To convert a string array to an Int array and multiply each element by two you can use this
func multiplyInts(_ array: [String]) -> [Int] {
return array.compactMap(Int.init).map{$0 * 2}
}
let result = multiplyInts(["1", "2", "3"]) // [2, 4, 6]
Below code may be useful for you
func multiplyInts(_ num: Int) -> Array<Any> {
let arr = Array(String(num))
var resultArr = [Int]()
for i in 0..<arr.count {
let strIn = String(arr[i])
if let intNum = Int(strIn) {
let numIn = intNum * 2
resultArr.append(numIn)
}
}
return Array(resultArr)
}
print(multiplyInts(123)) // [2, 4, 6]
Just use map.
func multiplyInts(_ num: [Int]) -> [Int] {
num.map { $0 * 2 }
}
Example:
print(multiplyInts([1, 2, 3]))
// Prints: [2, 4, 6]
If I have two int arrays such as
var array1 = [1,2,3]
var array2 = [1,2,3,5]
I'd like to be able to add the first element of the first array with the first element of the second array, and so on. However if an array has a different length than the other I'd like to keep the element that was not added in the return array. For this example my return array would be [2,4,6,5].
I tried using zip(array1,array2).map(+) but it would exclude the 5 from array2.
After adding the elements at the index positions which are common to both arrays (what you already did with zip and map) just append the remaining elements from both arrays (using append(contentsOf:) and dropFirst):
let array1 = [1, 2, 3]
let array2 = [1, 2, 3, 5]
var combined = zip(array1, array2).map(+)
let commonCount = combined.count
combined.append(contentsOf: array1.dropFirst(commonCount))
combined.append(contentsOf: array2.dropFirst(commonCount))
print(combined) // [2, 4, 6, 5]
AnySequence(zip: (1...3, [1, 2, 3, 5])).map {
Optional($0).map(+) ?? firstNonNil($0)!
}
public extension AnySequence {
/// Like `zip`, but with `nil` elements for the shorter sequence after it is exhausted.
init<Sequence0: Sequence, Sequence1: Sequence>(
zip zipped: (Sequence0, Sequence1)
) where Element == (Sequence0.Element?, Sequence1.Element?) {
self.init(
sequence(
state: (zipped.0.makeIterator(), zipped.1.makeIterator())
) { iterators in
((iterators.0.next(), iterators.1.next()) as Optional)
.filter { $0 != nil || $1 != nil }
}
)
}
}
public extension Optional {
/// Exchange two optionals for a single optional tuple.
/// - Returns: `nil` if either tuple element is `nil`.
init<Wrapped0, Wrapped1>(_ optionals: (Wrapped0?, Wrapped1?))
where Wrapped == (Wrapped0, Wrapped1) {
switch optionals {
case let (wrapped0?, wrapped1?):
self = (wrapped0, wrapped1)
default:
self = nil
}
}
/// Transform `.some` into `.none`, if a condition fails.
/// - Parameters:
/// - isSome: The condition that will result in `nil`, when evaluated to `false`.
func filter(_ isSome: (Wrapped) throws -> Bool) rethrows -> Self {
try flatMap { try isSome($0) ? $0 : nil }
}
}
public func firstNonNil<Element>(_ tuple: (Element?, Element?)) -> Element? {
switch tuple {
case (let _0?, _):
return _0
case (nil, let _1?):
return _1
case (nil, nil):
return nil
}
}
func combine2Arrays(array1:[Int], array2:[Int]) -> [Int] {
var finalArray:[Int] = []
let maxSize = max(array1.count, array2.count)
for i in 0..<maxSize {
let valToAdd1 = (array1.count > i ? array1[i] : 0)
let valToAdd2 = (array2.count > i ? array2[i] : 0)
let finalVal = valToAdd1 + valToAdd2
finalArray.append(finalVal)
}
return finalArray
}
print(combine2Arrays(array1: [1,2,3], array2: [1,2,3,5]))
OR
func combine2Arrays(array1:[Int], array2:[Int]) -> [Int] {
var finalArray:[Int] = zip(array1,array2).map(+)
let largerArray = array1.count > array2.count ? array1 : array2
let smallerArray = array1.count > array2.count ? array2 : array1
let min = smallerArray.count
let max = largerArray.count
for i in min..<max {
finalArray.append(largerArray[i])
}
return finalArray
}
print(combine2Arrays(array1: [1,2,3], array2: [1,2,3,5]))
You can fill your smaller array with zeroes, then use zip. inout means that arrays are mutable, or you can make the copy of function parameters inside the function to make them mutable.
private func combineArrays(array1: inout [Int], array2: inout [Int]) -> [Int] {
let maxSize = max(array1.count, array2.count)
if (array1.count > array2.count) {
array2.append(contentsOf: [Int](repeating: 0, count: maxSize - array2.count))
} else if (array2.count > array1.count) {
array1.append(contentsOf: [Int](repeating: 0, count: maxSize - array1.count))
}
return zip(array1, array2).map(+)
}
//javaScript
var array1 = [1,2,3,4,5];
var array2 = [9,7,8,6,5,6,7];
let a= array1.length;
let b = array2.length;
var array3 = [];
let c = a>b?a:b;
for(let i=0; i<c; i++){
if(i < a && i < b){
array3.push(array1[i] + array2[i]);
} else if(i >= a){
array3.push(array2[i])
} else{
array3.push(array1[i])
}
}
console.log(array3)
I would like to be able to find and replace occurrences of a substring in a native Swift string without bridging to the NS class. How can I accomplish this?
This is not a duplicate of this question, as that question is about replacing a single character. This question is about finding and replacing a substring, which may contain many characters.
Method without Foundation:
extension String {
func replacing(_ oldString: String, with newString: String) -> String {
guard !oldString.isEmpty, !newString.isEmpty else { return self }
let charArray = Array(self.characters)
let oldCharArray = Array(oldString.characters)
let newCharArray = Array(newString.characters)
var matchedChars = 0
var resultCharArray = [Character]()
for char in charArray {
if char == oldCharArray[matchedChars] {
matchedChars += 1
if matchedChars == oldCharArray.count {
resultCharArray.append(contentsOf: newCharArray)
matchedChars = 0
}
} else {
for i in 0 ..< matchedChars {
resultCharArray.append(oldCharArray[i])
}
if char == oldCharArray[0] {
matchedChars = 1
} else {
matchedChars = 0
resultCharArray.append(char)
}
}
}
return String(resultCharArray)
}
}
Example usage:
let myString = "Hello World HelHelloello Hello HellHellooo"
print(myString.replacing("Hello", with: "Hi"))
Output:
Hi World HelHiello Hi HellHioo
Method using Foundation:
You can use the replacingOccurrences method on the String struct.
let myString = "Hello World"
let newString = myString.replacingOccurrences(of: "World", with: "Everyone")
print(newString) // prints "Hello Everyone"
generic and pure Swift approach
func splitBy<T: RangeReplaceableCollection>(_ s:T, by:T)->[T] where T.Iterator.Element:Equatable {
var tmp = T()
var res = [T]()
var i:T.IndexDistance = 0
let count = by.count
var pc:T.Iterator.Element {
get {
i %= count
let idx = by.index(by.startIndex, offsetBy: i)
return by[idx]
}
}
for sc in s {
if sc != pc {
i = 0
if sc != pc {
} else {
i = i.advanced(by: 1)
}
} else {
i = i.advanced(by: 1)
}
tmp.append(sc)
if i == count {
tmp.removeSubrange(tmp.index(tmp.endIndex, offsetBy: -i)..<tmp.endIndex)
res.append(tmp)
tmp.removeAll()
}
}
res.append(tmp)
return res
}
func split(_ s:String, by:String)->[String] {
return splitBy(s.characters, by: by.characters).map(String.init)
}
extension RangeReplaceableCollection where Self.Iterator.Element: Equatable {
func split(by : Self)->[Self] {
return splitBy(self, by: by)
}
}
how to use it?
let str = "simple text where i would like to replace something with anything"
let pat = "something"
let rep = "anything"
let s0 = str.characters.split(by: pat.characters).map(String.init)
let res = s0.joined(separator: rep)
print(res) // simple text where i would like to replace anything with anything
let res2 = split(str, by: pat).joined(separator: rep)
print(res2) // simple text where i would like to replace anything with anything
let arr = [1,2,3,4,1,2,3,4,1,2,3]
let p = [4,1]
print(arr.split(by: p)) // [[1, 2, 3], [2, 3], [2, 3]]
If I’ve got a bunch of chained guard let statements, how can I diagnose which condition failed, short of breaking apart my guard let into multiple statements?
Given this example:
guard let keypath = dictionary["field"] as? String,
let rule = dictionary["rule"] as? String,
let comparator = FormFieldDisplayRuleComparator(rawValue: rule),
let value = dictionary["value"]
else
{
return nil
}
How can I tell which of the 4 let statements was the one that failed and invoked the else block?
The simplest thing I can think of is to break out the statements into 4 sequential guard else statements, but that feels wrong.
guard let keypath = dictionary["field"] as? String
else
{
print("Keypath failed to load.")
self.init()
return nil
}
guard let rule = dictionary["rule"] as? String else
{
print("Rule failed to load.")
self.init()
return nil
}
guard let comparator = FormFieldDisplayRuleComparator(rawValue: rule) else
{
print("Comparator failed to load for rawValue: \(rule)")
self.init()
return nil
}
guard let value = dictionary["value"] else
{
print("Value failed to load.")
self.init()
return nil
}
If I wanted to keep them all in one guard statement, I can think of another option. Checking for nils inside the guard statement might work:
guard let keypath = dictionary["field"] as? String,
let rule = dictionary["rule"] as? String,
let comparator = FormFieldDisplayRuleComparator(rawValue: rule),
let value = dictionary["value"]
else
{
if let keypath = keypath {} else {
print("Keypath failed to load.")
}
// ... Repeat for each let...
return nil
}
I don't even know if that will compile, but then I might as well have used a bunch of if let statements or guards to begin with.
What's the idiomatic Swift way?
Erica Sadun just wrote a good blog post on this exact topic.
Her solution was to hi-jack the where clause and use it to keep track of which guard statements pass. Each successful guard condition using the diagnose method will print the file name and the line number to the console. The guard condition following the last diagnose print statement is the one that failed. The solution looked like this:
func diagnose(file: String = #file, line: Int = #line) -> Bool {
print("Testing \(file):\(line)")
return true
}
// ...
let dictionary: [String : AnyObject] = [
"one" : "one"
"two" : "two"
"three" : 3
]
guard
// This line will print the file and line number
let one = dictionary["one"] as? String where diagnose(),
// This line will print the file and line number
let two = dictionary["two"] as? String where diagnose(),
// This line will NOT be printed. So it is the one that failed.
let three = dictionary["three"] as? String where diagnose()
else {
// ...
}
Erica's write-up on this topic can be found here
Normally, a guard statement doesn't let you distinguish which of its conditions wasn't satisfied. Its purpose is that when the program executes past the guard statement, you know all the variables are non-nil. But it doesn't provide any values inside the guard/else body (you just know that the conditions weren't all satisfied).
That said, if all you want to do is print something when one of the steps returns nil, you could make use of the coalescing operator ?? to perform an extra action.
Make a generic function that prints a message and returns nil:
/// Prints a message and returns `nil`. Use this with `??`, e.g.:
///
/// guard let x = optionalValue ?? printAndFail("missing x") else {
/// // ...
/// }
func printAndFail<T>(message: String) -> T? {
print(message)
return nil
}
Then use this function as a "fallback" for each case. Since the ?? operator employs short-circuit evaluation, the right-hand side won't be executed unless the left-hand side has already returned nil.
guard
let keypath = dictionary["field"] as? String ?? printAndFail("missing keypath"),
let rule = dictionary["rule"] as? String ?? printAndFail("missing rule"),
let comparator = FormFieldDisplayRuleComparator(rawValue: rule) ?? printAndFail("missing comparator"),
let value = dictionary["value"] ?? printAndFail("missing value")
else
{
// ...
return
}
Very good question
I wish I had a good answer for that but I have not.
Let's begin
However let's take a look at the problem together. This is a simplified version of your function
func foo(dictionary:[String:AnyObject]) -> AnyObject? {
guard let
a = dictionary["a"] as? String,
b = dictionary[a] as? String,
c = dictionary[b] else {
return nil // I want to know more ☹️ !!
}
return c
}
Inside the else we don't know what did go wrong
First of all inside the else block we do NOT have access to the constants defined in the guard statement. This because the compiler doesn't know which one of the clauses did fail. So it does assume the worst case scenario where the first clause did fail.
Conclusion: we cannot write a "simple" check inside the else statement to understand what did not work.
Writing a complex check inside the else
Of course we could replicate inside the else the logic we put insito the guard statement to find out the clause which did fail but this boilerplate code is very ugly and not easy to maintain.
Beyond nil: throwing errors
So yes, we need to split the guard statement. However if we want a more detailed information about what did go wrong our foo function should no longer return a nil value to signal an error, it should throw an error instead.
So
enum AppError: ErrorType {
case MissingValueForKey(String)
}
func foo(dictionary:[String:AnyObject]) throws -> AnyObject {
guard let a = dictionary["a"] as? String else { throw AppError.MissingValueForKey("a") }
guard let b = dictionary[a] as? String else { throw AppError.MissingValueForKey(a) }
guard let c = dictionary[b] else { throw AppError.MissingValueForKey(b) }
return c
}
I am curious about what the community thinks about this.
One possible (non-idiomatic) workaround: make use of the where clause to track the success of each subsequent optional binding in the guard block
I see nothing wrong with splitting up your guard statements in separate guard blocks, in case you're interested in which guard statement that fails.
Out of a technical perspective, however, one alternative to separate guard blocks is to make use of a where clause (to each optional binding) to increment a counter each time an optional binding is successful. In case a binding fails, the value of the counter can be used to track for which binding this was. E.g.:
func foo(a: Int?, _ b: Int?) {
var i: Int = 1
guard let a = a where (i+=1) is (),
let b = b where (i+=1) is () else {
print("Failed at condition #\(i)")
return
}
}
foo(nil,1) // Failed at condition #1
foo(1,nil) // Failed at condition #2
Above we make use of the fact that the result of an assignment is the empty tuple (), whereas the side effect is the assignment to the lhs of the expression.
If you'd like to avoid introducing the mutable counter i prior the scope of guard clause, you could place the counter and the incrementing of it as a static class member, e.g.
class Foo {
static var i: Int = 1
static func reset() -> Bool { i = 1; return true }
static func success() -> Bool { i += 1; return true }
}
func foo(a: Int?, _ b: Int?) {
guard Foo.reset(),
let a = a where Foo.success(),
let b = b where Foo.success() else {
print("Failed at condition #\(Foo.i)")
return
}
}
foo(nil,1) // Failed at condition #1
foo(1,nil) // Failed at condition #2
Possibly a more natural approach is to propagate the value of the counter by letting the function throw an error:
class Foo { /* as above */ }
enum Bar: ErrorType {
case Baz(Int)
}
func foo(a: Int?, _ b: Int?) throws {
guard Foo.reset(),
let a = a where Foo.success(),
let b = b where Foo.success() else {
throw Bar.Baz(Foo.i)
}
// ...
}
do {
try foo(nil,1) // Baz error: failed at condition #1
// try foo(1,nil) // Baz error: failed at condition #2
} catch Bar.Baz(let num) {
print("Baz error: failed at condition #\(num)")
}
I should probably point out, however, that the above is probably closer to be categorized as a "hacky" construct, rather than an idiomatic one.
The simplest thing I can think of is to break out the statements into 4 sequential guard else statements, but that feels wrong.
In my personal opinion, the Swift way shouldn't require you to check whether the values are nil or not.
However, you could extend Optional to suit your needs:
extension Optional
{
public func testingForNil<T>(#noescape f: (Void -> T)) -> Optional
{
if self == nil
{
f()
}
return self
}
}
Allowing for:
guard let keypath = (dictionary["field"] as? String).testingForNil({ /* or else */ }),
let rule = (dictionary["rule"] as? String).testingForNil({ /* or else */ }),
let comparator = FormFieldDisplayRuleComparator(rawValue: rule).testingForNil({ /* or else */ }),
let value = dictionary["value"].testingForNil({ /* or else */ })
else
{
return nil
}
My two cents:
Since Swift doesn't let me add the where in the guard let, I came up with this solution instead:
func validate<T>(_ input: T?, file: String = #file, line: Int = #line) -> T? {
guard let input = input else {
print("Nil argument at \(file), line: \(line)")
return nil
}
return input
}
class Model {
let id: Int
let name: String
init?(id: Int?, name: String?) {
guard let id = validate(id),
let name = validate(name) else {
return nil
}
self.id = id
self.name = name
}
}
let t = Model(id: 0, name: "ok") // Not nil
let t2 = Model(id: 0, name: nil) // Nil
let t3 = Model(id: nil, name: "ok") // Nil
I think other answers here are better, but another approach is to define functions like this:
func checkAll<T1, T2, T3>(clauses: (T1?, T2?, T3?)) -> (T1, T2, T3)? {
guard let one = clauses.0 else {
print("1st clause is nil")
return nil
}
guard let two = clauses.1 else {
print("2nd clause is nil")
return nil
}
guard let three = clauses.2 else {
print("3rd clause is nil")
return nil
}
return (one, two, three)
}
And then use it like this
let a: Int? = 0
let b: Int? = nil
let c: Int? = 3
guard let (d, e, f) = checkAll((a, b, c)) else {
fatalError()
}
print("a: \(d)")
print("b: \(e)")
print("c: \(f)")
You could extend it to print the file & line number of the guard statement like other answers.
On the plus side, there isn't too much clutter at the call site, and you only get output for the failing cases. But since it uses tuples and you can't write a function that operates on arbitrary tuples, you would have to define a similar method for one parameter, two parameters etc up to some arity. It also breaks the visual relation between the clause and the variable it's being bound to, especially if the unwrapped clauses are long.
This code can be used for all guard and if logic tests like optional, bool and case tests. It prints a line of a logic test which failed.
class GuardLogger {
var lastGoodLine: Int
var lineWithError: Int { lastGoodLine + 1 }
var file: String
var function: String
init(file: String = #file, function: String = #function, line: Int = #line) {
self.lastGoodLine = line
self.file = file
self.function = function
}
func log(line: Int = #line) -> Bool {
lastGoodLine = line
return true
}
func print() {
Swift.print([file, function, String(lineWithError)].joined(separator: " "))
}
}
let testBoolTrue = true
let testBoolFalse = false
let guardLogger = GuardLogger()
guard
testBoolTrue, guardLogger.log(),
let testOptionalBoolTrue = Optional(testBoolTrue), guardLogger.log(),
let selfIsViewController = self as? UIViewController, guardLogger.log(),
testBoolTrue == false, guardLogger.log() // this fails
else {
print(guardLogger.lastGoodLine)
fatalError()
}
I am using the following code in xCode 6.4 to split strings inside an array into arrays:
func getData() -> [String]
{
let data = navData
// navData is like:
// A|xxx|xxx|xxx
// R|ccc|ccc|ccc
// N|ccc|ccc|ccc
// N|ccc|ccc|ccc
return split(data) { $0 == "\n" }
}
let data:[String] = getData()
func search(query:(String, Int)) -> [String]
{
let recs:[String] = data.filter { $0.hasPrefix(query.0) }
var cols: [String] = recs.map { split( recs ) { $0 == "|" } }
}
func searchQueries() -> [(String, Int)]
{
return [("N", 1)] //key, column index
}
for q:(String, Int) in searchQueries()
{
var results:[String] = search(q)
for x in results
{
result = results[0]
}
}
It used to work before, but I guess swift was changed in 1.2 and it gives the following error now:
Cannot invoke 'map' with an argument list of type '(() -> _)'
Any suggestions?
Thank you!
After discovering that in Swift two you have to split strings by using its characters property, I made this work in playground:
let recs = ["col1|col2|col3", "1|2|3"]
let cols = recs.map {
split($0.characters) { $0 == "|" }.map {String($0)}
}
cols.first // ["col1", "col2", "col3"]
cols.last // ["1", "2", "3"]
Note that in Swift 2 beta 2 you can also use {String.init} at the end.
To make this work in Swift 1.2, remove .characters.