blob: 920613a5d9f68ce862379293a62aa5910db6818e [file] [log] [blame]
// DictOfArraysToArrayOfDicts benchmark
//
// Description: Convert a dictionary of [key: [values]] to an array of
// dictionaries [[key: value]] using zipWith.
// Source: https://gist.github.com/airspeedswift/3675952127ee775551b0
import TestsUtils
public var DictOfArraysToArrayOfDicts = BenchmarkInfo(
name: "DictOfArraysToArrayOfDicts",
runFunction: run_DictOfArraysToArrayOfDicts,
tags: [.algorithm, .Dictionary]
)
@inline(never)
public func run_DictOfArraysToArrayOfDicts(_ N: Int) {
let returnedFromServer = [
"title": ["abc", "def", "ghi"],
"time": ["1234", "5678", "0123"],
"content": ["qwerty", "asdfg", "zxcvb"],
]
var pairs: [[(String, String)]] = []
var inverted: [[(String, String)]] = []
var arrayOfDicts: [[String: String]] = [[:]]
for _ in 1...100*N {
pairs = returnedFromServer.map {
(key, value) in value.map { (key, $0) }
}
inverted = zipWith(pairs[0], pairs[1], pairs[2]) {
[$0] + [$1] + [$2]
}
arrayOfDicts = inverted
.map { $0.map { (key: $0.0, value: $0.1) } }
.map { Dictionary($0) }
if !(arrayOfDicts.count == 3) {
break
}
}
CheckResults(arrayOfDicts.count == 3)
}
// Given [
// "title" : ["abc", "def"],
// "time" : ["1234", "5678", "0123"],
// "content":["qwerty", "asdfg", "zxcvb"]
// ]
//
// how do you get to this:
//
// [
// ["title" : "abc",
// "time" : "1234",
// "content": "qwerty"],
// ["title" : "def",
// "time" : "5678",
// "content": "asdfg"],
// ["title" : "ghi",
// "time" : "0123",
// "content": "zxcvb"]]
public func zip3 <
A: Sequence,B: Sequence,C: Sequence
> (_ a: A, _ b: B, _ c: C) -> ZipSequence3<A, B, C> {
return ZipSequence3(a, b, c)
}
// Sequence of tuples created from values from three other sequences
public struct ZipSequence3<A: Sequence,B: Sequence,C: Sequence> {
private var a: A
private var b: B
private var c: C
public init (_ a: A, _ b: B, _ c: C) {
self.a = a
self.b = b
self.c = c
}
}
extension ZipSequence3 {
public struct Iterator {
private var a: A.Iterator
private var b: B.Iterator
private var c: C.Iterator
public init(_ a: A, _ b: B, _ c: C) {
self.a = a.makeIterator()
self.b = b.makeIterator()
self.c = c.makeIterator()
}
}
}
extension ZipSequence3.Iterator: IteratorProtocol {
public typealias Element = (A.Element,B.Element,C.Element)
public mutating func next() -> Element? {
switch (a.next(), b.next(), c.next()) {
case let (aValue?, bValue?, cValue?):
return (aValue, bValue, cValue)
default:
return nil
}
}
}
extension ZipSequence3: Sequence {
public typealias Element = (A.Element,B.Element,C.Element)
public typealias SubSequence = AnySequence<Element>
public func makeIterator() -> Iterator {
return Iterator(a, b, c)
}
}
// Iterator that creates tuples of values from three other generators
func zipWith<
A: Sequence, B: Sequence, C: Sequence, T
>(
_ a: A, _ b: B, _ c: C,
_ combine: (A.Element,B.Element,C.Element) -> T
) -> [T] {
return zip3(a,b,c).map(combine)
}
extension Dictionary {
// Construct from an arbitrary sequence with elements of the tupe
// `(Key,Value)`
init<S: Sequence> (_ seq: S) where S.Iterator.Element == Element {
self.init()
self.merge(seq)
}
// Merge a sequence of `(Key,Value)` tuples into the dictionary
mutating func merge<S: Sequence> (_ seq: S) where S.Element == Element {
var gen = seq.makeIterator()
while let (k, v) = gen.next() {
self[k] = v
}
}
}