How to do a join in Swift using the map tool?

I have two arrays of class objects having a common value in each object.

How do I do a join that would be the same as an SQL join?

For example.

Class AM_Template has the following public variables.

class AM_Template
{
public
var SystemID: String = ""
var ULSFileNo: String = ""
var CallSign: String = ""
var Class: String = ""
}

First, the class object AM_line is created using the template and is

var AM_line = AM_Template()

Next, two arrays are created with each record having the form AM_line

var AM0: [AM_Template] = [AM_line.self ]

var AM1: [AM_Template] = [AM_line.self

So now, I need to join AM and AM0 using the variable CallSign.

This is not the same as concatenating. The result of a join, in the SQL manner is an array containing both AM records and AM0 records aligned on the variable le that is in both arrays. There are left joins and right joins, but for now, I am interested in just joins where the values of CallSign are equal.

I’ve looked at the Swift map statement, but haven’t come across anything that actually creates a join as would be similar to an SQL join. How might that be done in Swift?

I'd recommend to use the standard convention of using camelCase for variable names and PascalCase for type names. Also embed code in triple ``` to format it nicely.

Something like that:

public class AMTemplate {
    public var systemID: String = ""
    public var ulsFileNo: String = ""
    public var callSign: String = ""
    public var theClass: String = ""
}

var line = AMTemplate()
var line0: [AMTemplate] = [line ]
var line1: [AMTemplate] = [line]

Let me show you a slightly different example, hopefully it'd answer your question:

struct Student {
    var id: Int
    var name: String
    var schoolId: Int?
}
struct School {
    var id: Int
    var name: String
}
struct StudentSchool {
    var student: Student?
    var school: School?
}
var students: [Student] = [
    Student(id: 1, name: "bob", schoolId: 1),
    Student(id: 2, name: "sarah", schoolId: 2),
    Student(id: 3, name: "gil", schoolId: 1),
    Student(id: 4, name: "adam", schoolId: nil)
]
var schools: [School] = [
    School(id: 1, name: "UCL"),
    School(id: 2, name: "UWE"),
    School(id: 3, name: "UCD")
]

func innerJoin() -> [StudentSchool] {
    students.compactMap { student in
        let school = schools.first { $0.id == student.schoolId }
        guard let school else { return nil }
        return StudentSchool(student: student, school: school)
    }
}

func leftOuterJoin() -> [StudentSchool] {
    students.map { student in
        let school = schools.first { $0.id == student.schoolId }
        return StudentSchool(student: student, school: school)
    }
}
2 Likes

Thank you very much. I am slowly making my way through your comments and translating them to my situation. I understand your comment about the camelCase.

In the example of func innerJoin, is the “student” variable the same as the “struct Student” listed above or is it a new variable. If it is new, how is it defined?

It looks like the “school” variable is a new variable because it is preceded by “let”.
Thank you.

I figured out the answer out the answer to my previous reply asking about the variable "student". It became obvious once I saw the answer. I have your code working in a program and am working to better understand it as i translate it to my project. Thank you.

Glad to be of help.

Another option would be to use references:

class Student {
    var name: String
    init(...) { ... }
}
class School {
    var name: String
    init(...) { ... }
}
struct StudentSchool { // or class
    var student: Student
    var school: School
}
var studentSchools: [StudentSchool] = ...

"studentSchools" here would be effectively the inner join result with no extra code needed. Note that in this example "id" fields was not needed (to emphasise that I removed them) as classes have built-in identity.

Thank you. I'll take a look at this second method.