Более производительно фильтровать массив или устанавливать, а затем преобразовывать в массив? (Свифт) - PullRequest
0 голосов
/ 06 августа 2020

У меня есть список из примерно 1000 объектов, содержащих несколько свойств. Мой пользовательский интерфейс требует, чтобы они были упорядочены, и я могу их отфильтровать.

Я понимаю, что наборы намного более производительны, поэтому мой вопрос: лучше ли просто использовать массив и фильтровать его или хранить набор внутри, выполнить для него всю фильтрацию, а затем всегда преобразовывать его обратно в массив перед возвратом в пользовательский интерфейс?

1 Ответ

2 голосов
/ 06 августа 2020

Для всего 1000 объектов это не имеет особого значения.

Вы можете попробовать следующий тест (для 1 миллиона объектов):

struct Foo: Hashable {
    let id: Int
    let name: String
}

let fooArr: [Foo] = (1...1_000_000).map { Foo(id: $0, name: "hkafghhkjdsgfajhkgfkjhasdf") }
let fooSet: Set<Foo> = Set(fooArr)

let start1 = CFAbsoluteTimeGetCurrent()
let filteredArr = fooArr.filter { $0.id.isMultiple(of: 2) }
let diff1 = CFAbsoluteTimeGetCurrent() - start1
print("Array: \(diff1) seconds")
// prints "Array: 4.004199028015137 seconds"

let start2 = CFAbsoluteTimeGetCurrent()
let filteredSetToArr = Array(fooSet.filter { $0.id.isMultiple(of: 2) })
let diff2 = CFAbsoluteTimeGetCurrent() - start2
print("Set: \(diff2) seconds")
// prints "Set: 4.139569997787476 seconds"

Опять же, здесь не так много разница. Фактические значения могут отличаться, но относительная разница должна быть одинаковой для каждой попытки.

Я использовал -Ofast уровень оптимизации.

Вы даже можете провести более подробные тесты:

let fooArr: [Foo] = (1...1_000_000).map { Foo(id: $0, name: "hkafghhkjdsgfajhkgfkjhasdf") }
let fooSet: Set<Foo> = Set(fooArr)

let start1 = CFAbsoluteTimeGetCurrent()
let filteredArr = fooArr.filter { $0.id.isMultiple(of: 2) }
let diff1 = CFAbsoluteTimeGetCurrent() - start1
print("Array filtering: \(diff1) seconds")

let start2 = CFAbsoluteTimeGetCurrent()
let filteredSet = Array(fooSet.filter { $0.id.isMultiple(of: 2) })
let diff2 = CFAbsoluteTimeGetCurrent() - start2
print("Set filtering: \(diff2) seconds")

let start3 = CFAbsoluteTimeGetCurrent()
let filteredSetToArr = Array(filteredSet)
let diff3 = CFAbsoluteTimeGetCurrent() - start3
print("Set to Array: \(diff3) seconds")

print("Set total: \(diff2 + diff3) seconds")

, и результат будет:

Array filtering: 1.5497009754180908 seconds
Set filtering: 1.2836240530014038 seconds
Set to Array: 1.895427703857422e-05 seconds
Set total: 1.2836430072784424 seconds

Обратите внимание, что фильтрация намного дороже, чем преобразование из Set в Array.

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