[For beginners] Let's be able to coat like Swift!

Swift is one of the modern languages. It can be said to be one of the latest languages because it is updated every year (although it is difficult to deal with it every time ...).

This time, I will introduce maps, filters, and forEach that are often used in modern languages. I often use it in other languages, so I think it's worth remembering.

Once you get used to it, you will start to think about whether any process can be expressed using map.

map

Example

struct User {
    let id: String
    let name: String
}

let users = [
    User(id: "111", name: "aaa"),
    User(id: "112", name: "bbb"),
    User(id: "113", name: "ccc"),
    User(id: "114", name: "ddd"),
    User(id: "115", name: "eee"),
    User(id: "116", name: "fff"),
]

var result = [String]()
for user in users {
    result.append(user.id)
}

print(result)
// ["111", "112", "113", "114", "115", "116"]

A String type array is created by collecting User ids. I think I'll learn to coat it like this in university classes.

But with Swift you can write in shorter code.

struct User {
    let id: String
    let name: String
}

let users = [
    User(id: "111", name: "aaa"),
    User(id: "112", name: "bbb"),
    User(id: "113", name: "ccc"),
    User(id: "114", name: "ddd"),
    User(id: "115", name: "eee"),
    User(id: "116", name: "fff"),
]

let result = users.map { $0.id }

print(result)
// ["111", "112", "113", "114", "115", "116"]

You can write in just one line by using map! If you are not sure about $ 0, please check here.

let result = users.map { user in
    user.id
}

I think you can understand it by this description method (similar to for ~ in). If you omit user in, you can express it as $ 0.

Conclusion

** map can do some processing on each element and return the result as an array! ** **

compactMap

Example

struct User {
    let id: String
    let name: String
}

let users = [
    User(id: "111", name: "aaa"),
    User(id: "112", name: "bbb"),
    User(id: "113", name: "ccc"),
    User(id: "a114", name: "ddd"),
    User(id: "a115", name: "eee"),
    User(id: "a116", name: "fff"),
]

let stringUserIdList = users.map { $0.id }
var result = [Int]()
for stringUserId in stringUserIdList {
    if let id = Int(stringUserId) {
        result.append(id)
    }
}

print(result)
// [111, 112, 113]

Earlier, I created an array of Strings easily using map. However, you may want to convert id to Int instead of String to make an array. If it is left as it is, the source code will be long after all.

Use compactMap in such cases.

let result = users
    .compactMap { Int($0.id) }

print(result)
// [111, 112, 113]

users.map {Int ($ 0.id)} returns an array of Int ?. Of course, if you try to cast from String to Int, you will not be able to cast 100%, so Int? Will be returned.

But compactMap removes the nil. Therefore, the returned type will be an array of Ints.

Conclusion

** compactMap can do something with each element and return the result as an array without nil! ** **

flatMap

Example

let users = [
    [
        User(id: "101", name: "man1"),
        User(id: "102", name: "man2"),
        User(id: "103", name: "man3"),
        User(id: "104", name: "man4"),
        User(id: "105", name: "man5")
    ],
    [
        User(id: "201", name: "women1"),
        User(id: "202", name: "women2"),
        User(id: "203", name: "women3"),
        User(id: "204", name: "women4"),
        User(id: "205", name: "women5")
    ]
]
var result = [String]()

//The name gender is not good...
for gender in users {
    for user in gender {
        result.append(user.id)
    }
}

print(result)
// ["101, "102", "103", "104", "105", "201", "202", "203", "204", "205"]

In this way, suppose you have an associative array with separate males and females. When extracting all ids from this users, I think that it will be implemented like this.

Of course, the for statement is repeated twice ... But using flatMap makes it easy!

let result = users
    .flatMap { $0 }
    .map { $0.id }

print(result)
// ["101, "102", "103", "104", "105", "201", "202", "203", "204", "205"]

flatMap literally makes it flat.

Conclusion

** flatMap flattens deep elements in the hierarchy! ** **

Advantages of map, compactMap, flatMap

--Source code becomes shorter ――Readability improves if you have knowledge --If you don't know some members, you should hold a study session and share it. --You don't have to worry about variable names ――The more complicated the process, the more the naming of variables that hold intermediate elements is appreciated.

For your reference...

In previous Swift versions, compactMap did not exist. Certainly, flatMap also had the function of compactMap, so it seems that it was very complicated.

The latest version solves that problem, so use it often!

filter

Example

struct User {
    /// ID
    let id: String
    ///name
    let name: String
    ///Gender 1: Male, 2: Female, 0: Other
    let gender: Int
    ///height
    let height: Float
}

let users = [
    User(id: "001",
         name: "Tanjiro",
         gender: 1,
         height: 165),
    User(id: "102",
         name: "Nezuko",
         gender: 2,
         height: 153.0),
    User(id: "103",
         name: "When",
         gender: 1,
         height: 165.5),
    User(id: "104",
          name: "Inosuke",
          gender: 1,
          height: 164.0)
]
//Get only men
var mens = [User]()
//Get only Users under 164 cm
var result = [User]()
for user in users {
    if user.gender == 1 {
        mens.append(user)
    }
    if user.height <= 164.0 {
        result.append(user)
    }
}
print(mens)
print(result)

Like when I introduced the map A variable (array) that stores the acquired result is prepared, and what is passed by the if statement in the for statement is stored in the variable.

You can write a little cooler with filter.

//Get only men
let result = users.filter { $0.gender == 1 }
//Get only men under 164 cm
let result = users
    .filter { $0.gender == 1 }
    .filter { $0.height <= 164.0 }

Let's use it positively! !!

forEach

The purpose of use is the same as for ~ in. If you want to abbreviate it, you often use forEach.


// for~in
for user in users {
    print(user)
}

// forEach
users.forEach { print($0) }

Conclusion

** forEach can do something with each element! ** **

Recommended Posts

[For beginners] Let's be able to coat like Swift!
[For beginners] Ruby is said to be ruby, but what about it?
[Tips] How to solve problems with XCode and Swift for beginners
(For beginners) Swift UI view element collection
Let's learn SQL SELECT statement for beginners
[Ruby] How to use slice for beginners
[For beginners] How to debug in Eclipse
Swift beginners tried to implement microwave logic!
[Swift / For beginners] Write smartly with type inference
[Rails] Add page nation to table [For beginners]
Posts that may be useful for JNI beginners
[For beginners] How to implement the delete function
Swift beginners tried to implement vending machine logic!
[For super beginners] How to use autofocus: true
[Introduction to Java] Basics of java arithmetic (for beginners)
Let's use Java New FileIO! (Introduction, for beginners)
[For beginners] Where to review when a class cannot be found at compile time