Пересечение массива объекта в iOS Swift с эффективностью и без использования цикла for - PullRequest
0 голосов
/ 08 октября 2018

Я хочу пересечь два массива, которые содержат объекты «Люди», и размер массива может быть больше 10000 для каждого массива, и я хочу пересечь, используя «id» объектов без использования цикла for.Я уже использовал для решения моего цикла, но скорость медленная.Некоторые объекты People могут иметь одинаковые идентификаторы в обоих массивах, а некоторые объекты могут иметь разные идентификаторы.

Ниже приведен пример моего кода

Пример:

class People {

    var id:Int!

    var name:String!

}

let object1 = People(10, John)

let object2 = People(5, Rocky)

let array1 = [object1, object2, .... , object10000]

let array2 = [objectA1, objectA2, .... , objectA10000]

Ответы [ 4 ]

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

Предполагая, что вы хотите Array из People, который сделан из array2 с помощью , уберите объекты, которых нет в массиве1 .

Тогда просто 2 строки:

let idSet1 = Set(array1.lazy.map{$0.id})
let interSection = array2.filter{idSet1.contains($0.id)}

Код тестирования:

import Foundation

class People {
    var id: Int
    var name: String

    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
}

do {
    //Generate random testing data
    let array1: [People] = (0..<20000).filter{_ in Int.random(in: 0...1) == 0}.map{People(id: $0, name: "P($0)")}
    print(array1.count)
    let array2: [People] = (0..<20000).filter{_ in Int.random(in: 0...1) == 0}.map{People(id: $0, name: "P($0)")}
    print(array2.count)

    let start = Date()
    let idSet1 = Set(array1.lazy.map{$0.id})
    let interSection = array2.filter{idSet1.contains($0.id)}
    let end = Date()
    print(interSection.count, end.timeIntervalSince(start))
}
0 голосов
/ 08 октября 2018

Вы можете создать Set с PeopleIds и Set with Object Id, что-то вроде этого:

let peoples = ...
let objects = ...

let peoplesIds = peoples.map { $0.id }
let objectsIds = objects.map { $0.id }

let peoplesIdsSet = Set(peoplesIds)
let objectsIdsSet= Set(objectsIds)

let intersectionsIds = Array(peoplesIdsSet.intersection(objectsIdsSet))

Также я советую вам поставить его работать в фоновом потоке, что-то вроде этого:

DispatchQueue.global(qos: .background).async {

    findIntersecionsIds()

    DispatchQueue.main.async {
        // done
    }
}
0 голосов
/ 08 октября 2018

Лучший способ выполнить пересечение - это использовать Set.Чтобы добавить ваши предметы в набор, они должны быть Hashable.Вот реализация вашего People класса, который Hashable и CustomStringConvertible (чтобы его можно было красиво напечатать):

class People: Hashable, CustomStringConvertible {

    var id: Int
    var name: String

    var hashValue: Int { return id }
    var description: String { return "People(name: \(name), id: \(id)" }


    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }

    // In order to conform to Hashable, you also need to be Equatable
    // Here we define equality as having the same id        
    static func ==(lhs: People, rhs: People) -> Bool {
        return lhs.id == rhs.id
    }
}

let object1 = People(id: 10, name: "John")
let object2 = People(id: 5, name: "Rocky")

let array1 = [object1, object2]

let array2 = [People(id: 10, name: "John"), People(id: 7, name: "Jane")]

let intersection = Array(Set(array1).intersection(array2))
print(intersection)
[People(name: John, id: 10]
0 голосов
/ 08 октября 2018

Вот простой пример

Предположим, ваша структура

struct User:Hashable {
    let id:Int
}

и ваш массив

let array1 = [User(id:1),User(id:2),User(id:3),User(id:4),User(id:5)]
let array2 = [User(id:1),User(id:20),User(id:3),User(id:4),User(id:5)]

Теперь вы можете создать набор

let set1:Set<Int> = Set(array1.map{$0.id})
let set2:Set<Int> = Set(array2.map{$0.id})

и

let unique = set1.intersection(set2)
let elements = (array1 + array2).filter{unique.contains($0.id)}
print(elements)

Надеюсь, что это полезно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...