WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Checkpoint 5: Lucky Numbers

Forums > 100 Days of SwiftUI

For Checkpoint 5 Paul challenges us to filter the odd numbers from an array, sort them, then print each integer in a specific format. Furthermore, he challenged us to do this with closures and one line of code.

Try it on your own before peeking at my solution!

let luckyNumbers = [ 7, 4, 38, 21, 16, 15, 12, 33, 31, 49]
print("\n\n======================= Challenge 5")
let _ = luckyNumbers
    .filter { !$0.isMultiple(of: 2) }   // filter out even numbers
    .sorted()                           // sort the odd numbers
    .map { "\($0) is a lucky number." } // map to strings
    .forEach{ print($0) }               // print each resulting string

2      

Well I figured out the filter (though I used $0 % 2 != 0 rather than !$0.isMultiple(of: 2) ) sorted and map but completely forgot about the .forEach() being available. Doh!

2      

If you're not going to be holding on to the transformed array, you should combine these two lines:

    .map { "\($0) is a lucky number." } // map to strings
    .forEach{ print($0) }               // print each resulting string

into:

    .forEach { print("\($0) is a lucky number") }

That reduces the number of times you have to loop through the entire array. (You are looping once with filter, once with sorted, once with map and then one final time with forEach.) Not such a big deal with a small number of items, but it can add up.

1      

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

I went to the ugly way I guess but the result is here ;)

  • let luckyNumbers = [7, 4, 38, 21, 16, 15, 12, 33, 31, 49]
  • var n = (luckyNumbers.count) - 1
  • for i in 0...n {
  • var testEven = luckyNumbers.sorted()[i]
  • if testEven % 2 != 0 {
  • print("(testEven) is a lucky number")
  • }
  • }

1      

@Powergeek I sense a background in C, perhaps even some Basic!

What's the saying? If it's stupid and it works, then it's not stupid. (Probably many variations on this.)

The only fault I see in your code is that you stopped. Instead, you could have taken the opportunity to refactor and ask that important questions "Can this part be simpler? What about this part??"

For example:

var n = (luckyNumbers.count) - 1
for i in 0...n {
     // code
}

// can this be simpler? yes!
// try this...
for i in 0...(luckyNumbers.count - 1) {
     // code
}

Then look inside your loop... I see you sort the array every time you select a new number.

var testEven = luckyNumbers.sorted()[i]

// consider sorting the array before jumping into the loop.
let sortedLuckyNumbers = luckyNumbers.sorted()

As you refine and refactor, you can chip away at "the ugly" as you called it, and your code becomes more, uh? Swifty!

PS: Rather than using bullet points for your code, try the </> tag in the forum message editor. It will format your code for Swift. Excellent!

1      

@iMoei  

let luckyNumbers = [7, 4, 38, 21, 16, 15, 12, 33, 31, 49]

let thatEvenNumber = luckyNumbers.filter { $0 % 2 == 0 }

print(thatEvenNumber)

let ascendingSort = luckyNumbers.sorted { $0 < $1 }

print(ascendingSort)

let luckySorting = luckyNumbers.map { "($0) is a lucky number." }.joined(separator: "\n")

print(luckySorting)

   

@Obelix

How to print each statemnt in a new line? I tried this but didn't work:

let luckyNumbers = [7, 4, 38, 21, 16, 15, 12, 33, 31, 49]

let newLuckyNumbers = luckyNumbers.filter { $0 % 2 == 1 }
    .sorted{ $0 < $1 }
    .map { "\($0) is a lucky number "}

print("\(newLuckyNumbers) \n")

   

You left off the imporant line!

let luckyNumbers = [ 7, 4, 38, 21, 16, 15, 12, 33, 31, 49]
print("\n\n======================= Challenge 5")
let _ = luckyNumbers
    .filter { !$0.isMultiple(of: 2) }   // filter out even numbers
    .sorted()                           // sort the odd numbers
    .map { "\($0) is a lucky number." } // map to strings
    .forEach{ print($0) }               // !!!   <-------------print each resulting string

1      

Thanks.

   

Would this be an acceptable solution?

let luckyNumbers = [7, 4, 38, 21, 16, 15, 12, 33, 31, 49]
let oddLuckyNumbers = luckyNumbers.filter({ $0.isMultiple(of: 2) == false})
.sorted {$0 < $1}
.map{"\($0) is a lucky number."}
print(oddLuckyNumbers)

   

Mario asks:

Would this be an acceptable solution?

Of course!

If you struggled a bit with the logic, and failed once or twice, but ended with a working solution, it's a win!

Here and there your code can be tightened. But this will come with experience. For now, don't worry about it, let your logic flow as fast as you can type. First make it work, then revise the code later.

One small example:

{ $0.isMultiple(of: 2) == false}

Here, you are checking to see if some number ($0) is a multiple of 2. The function returns true or false. But you then perform another check to see if true == false, or if false == false

This might be considered redundant, duplicitive, and totally repetitive code.

You can simplify it, like so:

{ !$0.isMultiple(of: 2) }  // this only returns true or false for each value of $0

Both do the same, which is easier to read?

{  $0.isMultiple(of: 2) == false}  // maybe your intent is clearer?
{ !$0.isMultiple(of: 2) }          // maybe this is tighter code?

@twoStraws addresses similar code questions in several of his vids. It often comes down to personal preference, what he calls the Art of Programming. You and your coding team can demolish many pints at the pub, and not answer this question. (See Oxford Comma, Tabs vs Spaces, Duck-Sized Horses, etc.)

Keep coding! @twoStraws asks you to code every day to keep your brain working and learning. It's important.

1      

@Obelix Thank you for the breakdown. As a newbie to programming definitely not able to come up with that kind of syntax yet, so it's very very enlightning.

   

Well, since the desired result is simply the printed strings, and since we're forbidden to use interim variables, I did it like so:

let luckyNumbers = [7, 4, 38, 21, 16, 15, 12, 33, 31, 49]

luckyNumbers.filter { $0 % 2 != 0 }.sorted().map { print("\($0) is a lucky number.") }

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.