© Stefan Kaczmarek, Brad Lees, Gary Bennett 2019
Stefan Kaczmarek, Brad Lees and Gary BennettSwift 5 for Absolute Beginnershttps://doi.org/10.1007/978-1-4842-4868-3_9

9. Comparing Data

Stefan Kaczmarek1 , Brad Lees1 and Gary Bennett2
(1)
Phoenix, AZ, USA
(2)
Scottsdale, AZ, USA
 

In this chapter, we will discuss one of the most basic and frequent operations you will perform as you program: comparing data. In the bookstore example, you may need to compare book titles if your clients are looking for a specific book. You may also need to compare authors if your clients are interested in purchasing books by a specific author. Comparing data is a common task performed by developers. Many of the loops you learned about in Chapter 8 will require you to compare data so that you know when your code should stop looping.

Comparing data in programming is like using a scale. You have one value on one side and another value on the other side. In the middle, you have an operator. The operator determines what kind of comparison is being done. Examples of operators are “greater than,” “less than,” or “equal to.”

The values on either side of the scale are usually variables. You learned about the different types of variables in Chapter 3. In general, the comparison functions for different variables will be slightly different. It is imperative that you become familiar with the functions and syntax to compare data because this will form the basis of your development.

For the purposes of this chapter, we will use an example of a bookstore application. This application will allow users to log in to the application, search for books, and purchase them. We will cover the different ways of comparing data to show how they would be used in this type of application.

Revisiting Boolean Logic

In Chapter 4, we introduced Boolean logic. Because of its prevalence in programming, we will revisit this subject in this chapter and go into more detail.

The most common comparisons that you will program your application to perform are comparisons using Boolean logic. Boolean logic usually comes in the form of if/then statements. Boolean logic can have only one of two answers: yes or no. The following are some good examples of Boolean questions that you will use in your applications:
  • Is 5 larger than 3?

  • Does now have more than five letters?

  • Is 6/1/2010 later than today?

Notice that there are only two possible answers to these questions: yes and no. If you are asking a question that could have more than these two answers, that question will need to be worded differently for programming.

Each of these questions will be represented by an if/then statement. (For example, “If 5 is greater than 3, then print a message to the user.”) Each if statement is required to have some sort of relational operator. A relational operator can be something like “is greater than” or “is equal to.”

To start using these types of questions in your programs, you will first need to become familiar with the different relational operators available to you in the Swift language. We will cover them first. After that, you will learn how different variables can behave with these operators.

Using Relational Operators

Swift uses six standard comparison operators. These are the standard algebraic operators with only one real change: In the Swift language, as in most other programming languages, the “equal to” operator is made by two equals signs (==). Table 9-1 describes the operators available to you as a developer.
Table 9-1.

Comparison Operators

Operator

Description

>

Greater than

<

Less than

>=

Greater than or equal to

<=

Less than or equal to

==

Equal to

!=

Not equal to

Note

A single equals sign (=) is used to assign a value to a variable. Two equals signs (==) are needed to compare two values. For example, if(x=9) will try to assign the value of 9 to the variable x, but now Xcode throws an error in this case. if(x==9) will do a comparison to see whether x equals 9.

Comparing Numbers

One of the difficulties developers have is dealing with different data types in comparisons. Earlier in this book, we discussed the different types of variables. You may remember that 1 is an integer. If you wanted to compare an integer with a float such as 1.2, this will cause some issues. This is where type casting becomes handy.

Note

Type casting is the conversion of an object or variable from one type to another.

In the bookstore application, you will need to compare numbers in many ways. For example, let’s say the bookstore offers a discount for people who spend more than $30 in a single transaction. You will need to add the total amount the person is spending and then compare this to $30. If the amount spent is larger than $30, you will need to calculate the discount. See the following example:
var discountThreshold = 30
var discountPercent = 0
var totalSpent = calculateTotalSpent()
if totalSpent > discountThreshold {
    discountPercent = 10
}

Let’s walk through the code. First, you declare the variables (discountThreshhold, discountPercent, and totalSpent) and assign a value to them. Notice you do not need to specify the type of number for the variables. The type will be assigned when you assign it a value. You know that discountThreshold and discountPercent will not contain decimals, so the compiler will type them as Ints. In this example, you can assume you have a function called calculateTotalSpent , which will calculate the total spent in this current order and return the value as an Int. You then simply check to see whether the total spent is larger than the discount threshold; if it is, you set the discount percent. If we wanted a customer who spent exactly $30 to get the same discount, we could use a >= instead of a >.

Another action that requires the comparison of numbers is looping. As discussed in Chapter 4, looping is a core action in development, and many loop types require some sort of comparison to determine when to stop. Let’s take a look at a for loop:
var numberOfBooks: Int = 50
for y in 0..<numberOfBooks {
    doSomething()
}

In this example, you iterate, or loop, through the total number of books in the bookstore. The for statement is where the interesting stuff starts to happen. Let’s break it down.

The for loop declares a variable with an initial value of 0 and will increment it while it is less than numberOfBooks. This is a much quicker way of doing for loops than was required in Objective-C.

Creating an Example Xcode App

Now let’s create an Xcode application so you can start comparing numeric data.
  1. 1.

    Launch Xcode and select File ➤ New ➤ Playground to create a new playground. This chapter will use a playground to make it easier to play around with comparisons.

     
  2. 2.
    Select Blank as shown in Figure 9-1. Click Next.
    ../images/341013_5_En_9_Chapter/341013_5_En_9_Fig1_HTML.jpg
    Figure 9-1.

    Creating a new playground

     
  3. 3.

    On the next page, enter the name of your playground. Here we used Comparison as the name, but you can choose any name you like.

    Note Xcode Playgrounds, by default, are saved in the Documents folder in your user home.

     
  4. 4.

    Once the new playground is created, you will see the standard Xcode window.

     
  5. 5.

    Add the following line after the default code in the playground:

     
print("Hello World")

This line creates a new String with the contents Hello World and passes it to the print function that is used for debugging.

Xcode will automatically run the new line you added and show the result on the right-hand side as seen in Figure 9-2.
../images/341013_5_En_9_Chapter/341013_5_En_9_Fig2_HTML.jpg
Figure 9-2.

Playground output

  1. 1.

    Go to the beginning of the line that begins with print. This is the line that is responsible for printing the Hello World string. You are going to comment out this line by placing two forward slashes (//) in front of the line of code. Commenting out code tells Xcode to ignore it when it executes the code. In other words, code that is commented out will not run.

     
  2. 2.
    Once you comment out the line of code, the code will no longer be run so Hello World will no longer show in the playground as seen in Figure 9-3.
    ../images/341013_5_En_9_Chapter/341013_5_En_9_Fig3_HTML.jpg
    Figure 9-3.

    Playground output with commented out code

     
  3. 3.

    We want to use the log to output the results of comparisons. Add one line, as shown here:

    print("The result is \(6 > 5 ? "True" : "False")")
     

Note

The previous code, (6>5 ? "True" : "False"), is called a ternary operation. It is essentially just a simplified way of writing an if/else statement.

  1. 4.

    Place this line in your code. This line is telling your application to print The result is. Then it will print True if 6 is greater than 5, or it will print False if 5 is greater than 6. See Figure 9-4.

     
Because 6 is greater than 5, it will print “The result is True.”
../images/341013_5_En_9_Chapter/341013_5_En_9_Fig4_HTML.jpg
Figure 9-4.

Ternary output

You can change this line to test any comparisons we have already discussed in this chapter or any of the examples you will do later.

Let’s try another example.
        var i = 5
        var y = 6
        print("The result is \(y > i ? "True" : "False")")
 In this example, you create a variable and assign its value to 5. You then create another variable and assign the value to 6. You then change the print example to compare the variables I and y instead of using actual numbers.

Note

You may get compiler warnings when using this code in an actual Xcode project. The compiler will tell you that the false portion of the ternary operator will never be executed. The compiler can look at the values while you are typing the code and know that the comparison will always be true.

You will now explore other kinds of comparisons , and then you will come back to the application and test some of them.

Using Boolean Expressions

A Boolean expression is the easiest of all comparisons. Boolean expressions are used to determine whether a value is true or false. Here’s an example:
var j = 5
if  j > 0 {
    someCode()
}

The if statement will always evaluate to true because the variable j is greater than zero. Because of that, the program will run the someCode() method.

Note

In Swift, if a variable is optional and therefore not guaranteed to be assigned a value, you should use a question mark after the variable declaration. For example, var j becomes var j: Int?.

If you change the value of j to 0, the statement will evaluate to false because j is now 0.
var j = 0
if j > 0 {
    someCode()
}
Placing an exclamation point in front of a Boolean expression will change it to the opposite value (a false becomes a true, and a true becomes a false).
var j = 0
if !(j > 0) {
    someCode()
}

The second line now asks “If not j>0,” which, in this case, is true because j is equal to 0. This is an example of using an integer to act as a Boolean variable. As discussed earlier, Swift also has variables called Bool that have only two possible values: true or false.

Note

Swift, like many other programming languages, uses true or false when assigning a value to a Boolean variable.

Let’s look at an example related to the bookstore. Say you have a frequent buyers’ club that entitles all members to a 15 percent discount on all books they purchase. This is easy to check. You simply set the variable clubMember to true if the person is a member and false if he or she is not. The following code will apply the discount only to club members:
var discountPercent = 0
var clubMember= false
if clubMember {
    discountPercent = 15
}

Comparing Strings

Strings are a difficult data type for most C languages. In ANSI C (or standard C), a string is just an array of characters. Objective-C took the development of the string even further and made it an object called NSString. Swift has taken the String class even further and made it easier to work with. Many more properties and methods are available to you when working with an object. Fortunately for you, String has many methods for comparing data, which makes your job much easier.

Let’s look at an example. Here, you are comparing passwords to see whether you should allow a user to log in:
var enteredPassword = "Duck"
var myPassword = "duck"
var continueLogin = false
if enteredPassword == myPassword {
    continueLogin = true
}

The first line just declares a String and sets it value to Duck. The next line declares another String and sets its value to duck. In your actual code, you will need to get the enteredPassword string from the user.

The next line is the part of the code that actually does the work. You simply ask the strings if they are equal to each other. The example code will always be false because of the capital “D” in the enteredPassword vs. the lowercase “d” in the myPassword.

There are many other different comparisons you might have to perform on strings. For example, you may want to check the length of a certain string. This is easy to do.
var enteredPassword = "Duck"
var myPassword = "duck"
var continueLogin = false
if enteredPassword.count > 5 {
    continueLogin = true
}

Note

count is a property that can be used to count strings, arrays, and dictionaries.

This code checks to see whether the entered password is longer than five characters.

There will be other times when you will have to search within a string for some data. Fortunately, Swift makes this easy to do. String provides a function called contains, which allows you to search within a string for another string. The function contains takes only one argument, which is the string for which you are searching.
var searchTitle: String
var bookTitle: String
searchTitle = "Sea"
bookTitle = "2000 Leagues Under the Sea"
if bookTitle.contains(searchTitle) {
    addToResults()
}

This code starts off similarly to other examples you have examined. We create two variables. This example then takes a search term and checks to see whether the book title has that same search term in it. If it does, it adds the book to the results. This can be adapted to allow users to search for specific terms in book titles, authors, or even descriptions.

For a complete listing of the methods supported by String, see the Apple documentation at https://swift.org/documentation/#the-swift-programming-language .

Using the switch Statement

Up to this point, you’ve seen several examples of comparing data by simply using the if statement .
if someValue == SOME_CONSTANT {
    ...
} else if someValue == SOME_OTHER_CONSTANT {
    ...
} else if someValue == YET_SOME_OTHER_CONSTANT {
    ...
}

If you need to compare a variable to several constant values, you can use a different method that can simplify the comparison code: the switch statement.

Note

In Objective-C, you could only use values to compare in a switch statement. Swift allows developers more freedom in using the switch statement. With Swift, developers can now compare most objects including custom objects.

The switch statement allows you to compare one or more values against another variable.
var customerType = "Repeat"
switch  customerType {     // The switch statement followed by a begin brace
case "Repeat":       // Equivalent to if (customerType == "Repeat")
   ...               // Call functions and put any other statements here after the case.
   ...
case "New":
    ...
    ...
case "Seasonal":                   ...
    ...
default:             // Swift requires all possibilities of a switch statement to be covered.
}  // End of the switch statement.

The switch statement is powerful, and it simplifies and streamlines comparisons to several different values.

In Swift, the switch statement is a powerful statement that can be used to simplify repeated if/else statements.

Comparing Dates

Dates are a fairly complicated variable type in any language, and unfortunately, depending on the type of application you are writing, they are common. Swift 4 has its own native Date type. The Swift Date class has a lot of nice methods that make comparing dates easy. We will focus on the compare function. The compare function returns a ComparisonResult, which has three possible values: orderedSame, orderedDescending, and orderedAscending.
// Today's Date
        let today: Date = Date()
        // Sale Date = Tomorrow
        let timeToAdd: TimeInterval = 60∗60∗24
        let saleDate: Date = today.addingTimeInterval(timeToAdd)
        var saleStarted = false
        let result: ComparisonResult  = today.compare(saleDate)
        switch result {
        case ComparisonResult.orderedAscending:
            // Sale Date is in the future
            saleStarted = false
        case ComparisonResult.orderedDescending:
            // Sale Start Date is in the past so sale is on
            saleStarted = true
        default:
            // Sale Start Date is now
            saleStarted = true
        }
This may seem like a lot of work just to compare some dates. Let’s walk through the code and see whether you can make sense of it.
let today: Date = Date()
let timeToAdd: TimeInterval = 60∗60∗24
let saleDate: Date = today.addingTimeInterval(timeToAdd)

Here, you declare two different Date objects . The first one, named today, is initialized with the system date or your device date. Before creating the second date, you need to add some time to the first date. You do this by creating a TimeInterval. This is a number in seconds. To add a day, you add 60*60*24. The second date, named saleDate, is initialized with a date sometime in the future. You will use this date to see whether this sale has begun. We will not go into detail about the initialization of Date objects.

The result of using the compare function of a Date object is a ComparisonResult. You have to declare a ComparisonResult to capture the output from the compare function.
let result = today.compare(saleDate)
This simple compares the two dates. It places the resulting ComparisonResult into the constant called result.
switch result {
         case ComparisonResult.orderedAscending:
            // Sale Date is in the future
            saleStarted = false
        case ComparisonResult.orderedDescending:
            // Sale Start Date is in the past so sale is on
            saleStarted = true
        default:
            // Sale Start Date is now
            saleStarted = true
        }

Now you need to find out what value is in the variable result. To accomplish this, you perform a switch statement that compares the result to the three different options for ComparisonResult. The first line finds out whether the sale date is greater than today’s date. This means that the sale date is in the future, and thus the sale has not started. You then set the variable saleStarted to false. The next line finds out whether the sale date is less than today. If it is, the sale has started, and you set the saleStarted variable to true. The next line just says default. This captures all other options. You know, though, that the only other option is orderedSame. This means the two dates and times are the same, and thus the sale is just beginning.

There are other methods that you can use to compare Date objects. Each of these methods will be more efficient at certain tasks. We have chosen the compare method because it will handle most of your basic date comparison needs.

Note

Remember that a Date holds both a date and a time. This can affect your comparisons with dates because it compares not only the date but also the time.

Combining Comparisons

As discussed in Chapter 4, you’ll sometimes need something more complex than a single comparison. This is where logical operators come in. Logical operators enable you to check for more than one requirement. For example, if you have a special discount for people who are members of your book club and who spend more than $30, you can write one statement to check this.
var totalSpent = 31
var discountThreshhold = 30
var discountPercent = 0
var clubMember = true
if totalSpent > discountThreshhold && clubMember {
    discountPercent = 15
}
We have combined two of the examples shown earlier. The new comparison line reads as follows: “If totalSpent is greater than discountThreshold AND clubMember is true, then set the discountPercent to 15.” For this to return true, both items need to be true. You can use || instead of && to signify “or.” You can change the previous line to this:
if totalSpent > discountThreshhold || clubMember  {
    discountPercent = 15
}

Now this reads as follows: “If totalSpent is greater than discountThreshold OR clubMember is true, then set the discount percent to 15.” This will return true if either of the options is true.

You can continue to use the logical operations to combine as many comparisons together as you need. In some cases, you may need to group comparisons using parentheses.

Summary

You’ve reached the end of the chapter! Here is a summary of the topics that were covered:
  • Comparisons: Comparing data is an integral part of any application.

  • Relational operators: You learned about the six standard relational operators and how each is used.

  • Numbers: Numbers are the easiest pieces of information to compare. You learned how to compare numbers in your programs.

  • Examples: You created a sample playground where you could test your comparisons and make sure that you are correct in your logic. Then you learned how to change the playground to add different types of comparisons.

  • Boolean: You learned how to check Boolean values.

  • Strings: You learned how strings behave differently from other pieces of information you have tested.

  • Dates: You learned how difficult it can be to compare dates and that you must be careful to make sure you are getting the response you desire.

Exercises

  • Modify the example playground to compare some string information.

  • Write a Swift application that determines whether the following years are leap years: 1800, 1801, 1899, 1900, 2000, 2001, 2003, and 2010. Output should be written to the console in the following format: The year 2000 is a leap year or The year 2001 is not a leap year. See http://en.wikipedia.org/wiki/Leap_year for information on determining whether a year is a leap year.