Swift provides powerful functions for working with arrays: map, filter, and reduce. These functions allow you to transform, filter, and combine array elements.

Before we go on, hereโ€™s some tips for users of other programming languages this year:

  • Rust supports the same functions map and filter. However, reduce is called fold.
  • Java supports map, filter, and reduce for Streams only.
  • C# supports similar functions called Select, Where, and Aggregate. You need to use LINQ in your project.
  • C++ supports similar functions with std::transform, std::copy_if, and either std::reduce or std::accumulate depending on your needs.

In this example, the function accepts one parameter called number and returns the square of that number. This function is applied to each of the numbers in the numbers array, creating a new array containing the squared numbers.

Filter

The filter function removes elements that donโ€™t match a condition.

The basic structure of function looks like this:

let result = myArray.filter { item in
    return item == conditionalValue
}

  • { item in ... }: This is a function that takes one parameter:
    • item: The next value in the array.
    • The function must return true or false. If it returns true, the item is included in the new array.

numbers = [1, 2, 3, 4, 5]
even_numbers = []
for number in numbers:
    if number % 2 == 0:
        even_numbers.append(number)
print(even_numbers)  # Output: [2, 4]

let numbers = [1, 2, 3, 4, 5]
let evenNumbers = numbers.filter { number in
    return number % 2 == 0
}
print(evenNumbers) // Output: [2, 4]

In this example, removes any number that does not satisfy the condition (i.e., not even). That is because number % 2 == 0 is a Boolean expression that returns true or false.

Use filter to use only words that are longer than four (4) characters. Print out the new array of words.

let words = ["apple", "cat", "banana", "dog", "grape", "kiwi"]

Reduce

The reduce function is a way to combine all elements in a array into a single value. If youโ€™ve used for loops in Python to sum numbers or join strings, reduce does the same thing, but in a more compact way.

The basic structure of reduce looks like this:

let result = array.reduce(initialValue) { result, item in
    return result + item
}

  • initialValue: This is where the total starts (like 0 for sum or "" for a sentence).
  • { result, item in ... }: This is a function that takes two parameters:
    • result: The value so far.
    • item: The next value in the array.
    • In the function, you decide how to combine the items.

numbers = [1, 2, 3, 4, 5]
total = 0
for number in numbers:
    total += number
print(total)  # Output: 15

let numbers = [1, 2, 3, 4, 5]
let total = numbers.reduce(0) { result, number in
    return result + number
}
print(total) // Output: 15

Each number is added to the total, just like in the loop. However, using reduce avoids having to create a variable (which would, otherwise, never be modified). Remember that avoiding unnecessary var is a desirable behaviour in Swift as it makes code more secure by preventing accidental overwriting of data that should be protected!

values = [3, 7, 2, 8, 5]
max_value = values
for value in values:
    if value > max_value:
        max_value = value
print(max_value)  # Output: 8
let values = [3, 7, 2, 8, 5]
let maxValue = values.reduce(values) { result, number in
    return max(result, number)
}
print(maxValue)  // Output: 8

This checks each number and keeps the biggest one.

In the example, the initial value is set to the first value in the values array; the max function then compares that number (result, currently 3) with the next number (number, which is 7 in the first run). The largest value (7) is returned, replacing the initial value (and result) with 7. In the next run, 7 is compared with 2; as 7 is still the largest value, it is returned again.

words = ["Python", "is", "fun"]
sentence = ""
for word in words:
    sentence = sentence + " " + word.upper()
print(sentence)

let words = ["Swift", "is", "fun"]
let sentence = words.reduce("") { result, word in
    return result + " " + word.uppercased()
}
print(sentence) // Output: " SWIFT IS FUN"

This builds a sentence by adding spaces between words.

Use reduce to find the product of all numbers in an array. Print the new array.

let numbers = [7, 14, 21, 28, 35]

Use reduce to find the longest word in an array. The initial value can be an empty string ("").

You can find the length of a word using the .count property. For example, "hello".count or someWord.count. This is equivalent to Pythonโ€™s len("hello") and len(some_word)

let words = ["apple", "banana", "grape", "strawberry", "kiwi"]

  • map transforms elements into a new array.
  • filter removes elements that donโ€™t meet a condition.
  • reduce combines elements into a single value.

These functions allow you to write more concise and functional Swift code.

You are given a array of student scores (out of 100). Your task is to process this array using map, filter, and reduce to find out the average score of students who passed (scored 50 or more).

Steps to Complete:

  1. Use map to curve the scores by adding 5 extra points to each studentโ€™s score.
  2. Use filter to keep only the passing scores (50 or more).
  3. Use reduce to calculate the average score of the passing students.

Use the following input:

let scores = [45, 78, 89, 32, 50, 92, 67, 41, 99, 56]

  1. Curve scores: [50, 83, 94, 37, 55, 97, 72, 46, 104, 61]
  2. Keep passing scores: [50, 83, 94, 55, 97, 72, 104, 61]
  3. Compute the average: (50 + 83 + 94 + 55 + 97 + 72 + 104 + 61) / 8 = 77
  4. When you print the correct value, take a screenshot of your code and the result in the Terminal. Upload the screenshot to the โ€œMap, Filter, and Reduceโ€ assignment in Google Classroom.

In this task, you will apply functional programming concepts in Swift using map, filter, and reduce to process and analyze movie ratings data. You will perform multiple transformations and calculations on the data using these higher-order functions.

You are provided with a dictionary where:

  • The keys are movie titles (Strings).
  • The values are arrays of integers representing user ratings (from 1 to 10).
let movieRatings: [String: ] = [
    "Inception": [9, 8, 10, 7, 6, 9, 8],
    "Interstellar": [10, 9, 10, 8, 7, 9],
    "The Dark Knight": [10, 10, 9, 9, 8, 10, 9],
    "Tenet": [7, 6, 8, 7, 5, 6, 7],
    "Dunkirk": [8, 9, 7, 8, 7, 8]
]

  1. Calculate Average Ratings (using mapValues)
    • Convert the dictionary into one where each movie title maps to its average rating.
    • Hint: use mapValues instead of map. This only extracts and transforms the values from the dictionary, leaving the keys intact. This means the new dictionary will have the same keys but new values; in this case, the new value is the average rating.
  2. Filter Movies with High Ratings (using filter)
    • Extract only movies with an average rating of 8.0 or higher.
  3. Find the Highest Rated Movie (using map and reduce)**
    • Extract the highest-rated movie from the filtered movies.
    • Hint: Use map to get an array of tuples (title, averageRating), then reduce to find the highest.
  4. Count Movies in Each Rating Category (using filter and reduce)**
    • Count how many movies fall into these rating categories:
      • 8.0 or higher
      • Between 6.0 and 7.99
      • Below 6.0
      • Hint: Use filter to classify movies into different categories, then reduce to count them.
  5. Find the Total Number of Ratings Given (Using map and reduce)**
    • Compute the total number of ratings submitted across all movies.
    • Hint: Use map to extract the number of ratings per movie, then reduce to sum them.
  6. Find the Highest Rated Movie Title in One Call (Using map, filter, and reduce Together)**
    • Find the title of the highest-rated movie (average rating of 8.0 or higher) in one functional chain.
    • Hint:
      1. Use map to create an array of tuples (title, averageRating).
      2. Use filter to remove movies with an average rating below 8.0.
      3. Use reduce to determine the movie with the highest rating.

Transforming an array with map

Map

The map function applies a transformation to each element in a array and returns a new array with the modified values.

How does it work?

The basic structure of map looks like this:

let result = myArray.map { item in
    return doSomethingTo(item)
}

Parts of map:

  • { item in ... }: This is a function that takes one parameter:
    • item: The next value in the array.
    • In your function, you decide how to transform each value.

Example: finding the square of numbers

Using a for Loop in Python:

numbers = [1, 2, 3, 4, 5]
squared_numbers = []
for number in numbers:
    squared_numbers.append(number * number)
print(squared_numbers)  # Output: [1, 4, 9, 16, 25]

Using map in Swift:

let numbers = [1, 2, 3, 4, 5]
let squaredNumbers = numbers.map { number in
    return number * number
}
print(squaredNumbers) // Output: [1, 4, 9, 16, 25]

๐Ÿ“ Task for map

Use map to double every number in an array. Print out the new array.

let numbers = [1, 3, 5, 7, 9]
Reload?