Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I properly format this Swift function to map an array?

Tags:

arrays

ios

swift

I'm trying to build a function with swift that will map an array, divide each value in the array by 3, then spit out a new array. This is what I have so far:

    func divideby3Map<T, U>(y: [T], z: T -> U) -> [U] {

        let array = [int]()
        let divideby3Array = array.map { [y] / 3 }

        return dividedby3Array
    }

    divideby3Map([1,2,3,4,5])

Where T and U are the original array, and the new array being returned respectively, and it's done using generics.

I'm sure this isn't written properly, I'm stuck in terms of the right syntax. For example, since the array being returned is represented by the generic [U], I assume I have to use it somewhere in the array being returned, not sure where though.

like image 690
KoftaClarence Avatar asked Apr 21 '15 21:04

KoftaClarence


People also ask

How do I map an array in Swift?

Example 2: Uppercase Array Of Strings Using map() In the above example, we have used the map() and uppercased() methods to transform each element of the languages array. The uppercased() method converts each string element of an array to uppercase. And the converted array is stored in the result variable.

How does map function work in Swift?

The map() Function in Swift. In Swift, you can use the built-in map() function to modify each element in a collection. The map() function loops through the collection, applying a function for each element. The map() function always returns an array where the transformed values are.

What is mapping Swift?

Swift version: 5.6. The map() method allows us to transform arrays (and indeed any kind of collection) using a transformation closure we specify. The return value will be an array of the same size, containing your transformed elements.

Can a function return an array in Swift?

Swift's functions have a single return type, such as Int or String , but that doesn't mean we can only return a single value. In fact, there are two ways we can send back multiple pieces of data: Using a tuple, such as (name: String, age: Int) Using some sort of collection, such as an array or a dictionary.


1 Answers

When writing a generic function, it’s sometimes easier to approach it in 3 steps: first write the code stand-alone using a specific type. Then write the code as a function, still with a specific type. Finally, change the function to be generic.

The first part, dividing an array by 3, can be done like this:

let a = [1,2,3,4,5]
// map is run on the array of integers, and returns a new
// array with the operation performed on each element in a:
let b = a.map { $0 / 3 }
// so b will be [0,0,1,1,1]
// (don’t forget, integer division truncates)

Note the closure you provide between the { } is an operation that will be applied to each element of the array. $0 represents the element, and you divide it by 3. You could also write it as a.map { i in i / 3 }.

To put this into its own function:

func divideby3Map(source: [Int]) -> [Int] {
    return source.map { $0 / 3 }
}

No need to declare a fresh array – map will create one for you. You can then return that directly (you can assign it to a temporary if you prefer, but that isn’t really necessary).

Finally, if you want to make it generic, start by adding a placeholder:

func divideby3Map<T>(source: [T]) -> [T] {
    return source.map { $0 / 3 }
}

Note, there’s only a need for one placeholder, T, because you are returning the exact same type you are passed in.

Except… this won’t compile, because the compiler doesn’t know that T is guaranteed to provide two critical things: the ability to divide (a / operator), and the ability to create new T from integer literals (i.e. to create a T with value 3 to divide by). Otherwise, what if we passed an array of strings or an array of arrays in?

To do this, we need to “constrain” T so our function will only accept as arguments types that provide these features. One such protocol we can use to constrain T is IntegerType, which does guarantee these features (as well as some other ones like +, * etc):

func divideby3Map<T: IntegerType>(source: [T]) -> [T] {
    return source.map { $0 / 3 }
}

divideby3Map(a) // returns [0,0,1,1,1]

let smallInts: [UInt8] = [3,6,9]
divideby3Map(smallInts)  // returns [1,2,3]
like image 184
Airspeed Velocity Avatar answered Nov 15 '22 06:11

Airspeed Velocity