Home > Enterprise >  How to combine two foreach to one in Swift?
How to combine two foreach to one in Swift?

Time:09-08

I have one function which is having some logic which have 2 foreach loop but i want to make code compact so I am trying to use compactmap

func getData() -> [String] {
        var ids = [String]()
        self.item?.connections?.forEach { connection in
            connection.validLine?.forEach { line in
                if let _ = line.connection?.links[LinkKey.dataGroups],
                   let dataGroups = line.dataGroupsCache, dataGroups.isContinue {
                    ids  = checkinGroups.connections?.compactMap { $0.id } ?? []
                }
            }
        }
    return ids
}

so instead of 2 foreach i am trying to make in one by using self.item?.connections?.compactMap({ $0.validline }) but I am getting error saying "Type of expression is ambiguous without more context"

CodePudding user response:

I don't see how you can do it without to forEach or compactMap. Here is a possible solution:

func getData() -> [String] {
    return item?.connections?.compactMap { connection in
        connection.validLine?.compactMap { line in
            guard let _ = line.connection?.links[LinkKey.dataGroups], line.dataGroupsCache?.isContinue == true else { return nil }
            return checkinGroups.connections?.compactMap(\.id)
        }
    }
}

CodePudding user response:

Here's a translation of your post into something that is compilable and a direct translation into a version that doesn't use forEach.

I changed connectionIds to ids in your example because otherwise, you might as well just return [].

class Example {
    func getData() -> [String] {
        var ids = [String]()
        self.item?.connections?.forEach { connection in
            connection.validLine?.forEach { line in
                if let _ = line.connection?.links[LinkKey.dataGroups],
                   let dataGroups = line.dataGroupsCache, dataGroups.isContinue {
                    ids  = checkinGroups.connections?.compactMap { $0.id } ?? []
                }
            }
        }
        return ids
    }

    func getDataʹ() -> [String] {
        guard let connections = item?.connections else { return [] }
        let numberOfProperLines = connections.flatMap { $0.validLine ?? [] }
            .filter { line in
                if let _ = line.connection?.links[LinkKey.dataGroups],
                   let dataGroups = line.dataGroupsCache, dataGroups.isContinue {
                    return true
                } else {
                    return false
                }
            }
            .count

        return (0..<numberOfProperLines).flatMap { _ in checkinGroups.connections?.compactMap(\.id) ?? [] }
    }

    var checkinGroups: CheckInGroups!
    var item: Item!
}

enum LinkKey: Int {
    case dataGroups
}
struct Item {
    let connections: [Connection]?
}

struct Connection {
    let id: String?
    let validLine: [Line]?
    let links: [LinkKey: Void]
}

struct Line {
    let dataGroupsCache: DataGroups?
    let connection: Connection?
}

struct DataGroups {
    let isContinue: Bool
}

struct CheckInGroups {
    let connections: [Connection]?
}
  • Related