Swift - найти конкретные различия в массивах структур - PullRequest
0 голосов
/ 24 октября 2018

Если у меня есть структура, скажите:

struct Subject { 
 var subjectID: String?
 var name: String?
 var note: String?
}

И у меня есть два массива этой структуры: Array1 и Array2.

Например:

Array1 = [(subjectID = "T", name = "H", note = "DF"), (subjectID = "F", name = "H", note = "SD")]
Array2 = [(subjectID = "T", name "G", note = "DF"), (subjectID = "R", name = "F", note = "SDF")]

Я хочу вернуть новый массив , который состоит из подмножества элементов из Array2, которые соответствуют полю subjectIDиз Array1, но имеют различные элементы name и / или note.

В приведенном выше примере возвращаемый массив будет иметь вид:

[(subjectID = "T", name "G", note = "DF")]

Поскольку он содержит то же subjectID (в данном случае T), что и в Array1, но поле name отличается.Обратите внимание, что поля для этого нового возвращаемого массива должны быть исходными значениями от Array2 (например: вам не нужно корректировать их, чтобы они соответствовали Array1)

Есть ли простой способ (например: one-две строки кода) чтобы сделать это без перебора?

Спасибо!

Ответы [ 4 ]

0 голосов
/ 24 октября 2018

Здесь есть хорошие ответы, я предпочитаю сделать тест простым.

Сначала настройка

struct Subject {
    var subjectID: String?
    var name: String?
    var note: String?
}

let array1 = [Subject(subjectID: "T", name: "H", note: "DF"), Subject(subjectID: "F", name: "H", note: "SD")]
let array2 = [Subject(subjectID: "T", name: "G", note: "DF"), Subject(subjectID: "R", name: "F", note: "SDF")]

Теперь давайте посмотрим на фактический алгоритм.array2.filter возвращает массив Subject с в array2, в котором блок возвращает true.array1.contains возвращает true, если любой из Subject s в array1 возвращает true.Сам тест - именно то, что вы описали.Являются ли идентификаторы темы одинаковыми и отличаются ли имя или примечание.

let result = array2.filter { s2 in
    array1.contains { s1 in
        s1.subjectID == s2.subjectID && (s1.name != s2.name || s1.note != s2.note)
    }
}
0 голосов
/ 24 октября 2018

Вы можете фильтровать элементы второго массива на основе элементов первого массива, так как:

let Array1 = [Subject(subjectID: "T", name: "H", note: "DF"), Subject(subjectID: "F", name: "H", note: "SD")]
let Array2 = [Subject(subjectID: "T", name: "G", note: "DF"), Subject(subjectID: "R", name: "F", note: "SDF")]

let result = Array2.filter { subject -> Bool in
    for s in Array1 {
        if subject.subjectID == s.subjectID && subject.name != s.name && subject.note != s.subjectID { return true }
    }

    return false
}

result должно содержать то, что вы запрашиваете.Имейте в виду, что он имеет сложность вложенной итерации (O(n²)).

0 голосов
/ 24 октября 2018

Я использовал forEach и фильтр в комбинации, чтобы найти запрошенные элементы

var result = [Subject]()
arr1.forEach( { subject in
    result.append(contentsOf: arr2.filter( { $0.subjectID == subject.subjectID && 
                                            ($0.name != subject.name || 
                                             $0.note != subject.note) }))
})

Чтобы получить немного более чистого кода, проверку можно сделать функцией в структуре

struct Subject {
   ...

    func isModifiedComparedTo(_ subject: Subject) -> Bool {
        return self.subjectID == subject.subjectID && (self.name != subject.name || self.note != subject.note)
    }
}

var result = [Subject]()
arr1.forEach( { subject in
    result.append(contentsOf: arr2.filter({$0.isModifiedComparedTo(subject)}))
})
0 голосов
/ 24 октября 2018

Вы можете сделать это следующим образом:

let subjectsByID = Dictionary(grouping: array1, by: { $0.subjectID })

let diff = array2.filter { subject in
    if let other = subjectsByID[subject.subjectID]?.first {
        return subject.name != other.name || subject.note != other.note
    } else {
        return false
    }
}

Он группирует субъекты в первом массиве по идентификатору, а затем фильтрует второй массив в зависимости от того, существует ли запись для этого идентификатора с другимимя или примечаниеВы не указали, что делать, если в первом массиве есть несколько записей с одинаковым идентификатором, поэтому он просто смотрит на первый.

...