Files
SwiftLint/Source/SwiftLintFramework/Extensions/Array+SwiftLint.swift
T
JP Simard a7a8a69fa2 Improve Array.parallelMap
By applying concepts from Swift Talk 90: https://talk.objc.io/episodes/S01E90-concurrent-map

Notably:
* Removing `@escaping` from block parameter
* Avoiding Array.append & sorting
* Using a constant DispatchQueue label
2018-03-07 09:27:35 -08:00

75 lines
2.2 KiB
Swift

//
// Array+SwiftLint.swift
// SwiftLint
//
// Created by Scott Hoyt on 1/11/16.
// Copyright © 2016 Realm. All rights reserved.
//
import Dispatch
import Foundation
extension Array where Element: NSTextCheckingResult {
func ranges() -> [NSRange] {
return map { $0.range }
}
}
extension Array where Element: Equatable {
var unique: [Element] {
var uniqueValues = [Element]()
for item in self where !uniqueValues.contains(item) {
uniqueValues.append(item)
}
return uniqueValues
}
}
extension Array {
static func array(of obj: Any?) -> [Element]? {
if let array = obj as? [Element] {
return array
} else if let obj = obj as? Element {
return [obj]
}
return nil
}
func group<U: Hashable>(by transform: (Element) -> U) -> [U: [Element]] {
return reduce([:]) { dictionary, element in
var dictionary = dictionary
let key = transform(element)
dictionary[key] = (dictionary[key] ?? []) + [element]
return dictionary
}
}
func partitioned(by belongsInSecondPartition: (Element) throws -> Bool) rethrows ->
(first: ArraySlice<Element>, second: ArraySlice<Element>) {
var copy = self
let pivot = try copy.partition(by: belongsInSecondPartition)
return (copy[0..<pivot], copy[pivot..<count])
}
func parallelFlatMap<T>(transform: @escaping ((Element) -> [T])) -> [T] {
return parallelMap(transform: transform).flatMap { $0 }
}
func parallelFlatMap<T>(transform: @escaping ((Element) -> T?)) -> [T] {
return parallelMap(transform: transform).flatMap { $0 }
}
func parallelMap<T>(transform: (Element) -> T) -> [T] {
var result = [T?](repeating: nil, count: count)
let resultAccumulatorQueue = DispatchQueue(label: "io.realm.SwiftLintFramework.map.resultAccumulator")
DispatchQueue.concurrentPerform(iterations: count) { idx in
let element = self[idx]
let transformed = transform(element)
resultAccumulatorQueue.sync {
result[idx] = transformed
}
}
return result.map { $0! }
}
}