blob: 76d978183b9c1b816352869629aaff6c5bd56b25 [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>: Sequence {
public typealias Iterator = ZipGenerator3
<A.Iterator, B.Iterator, C.Iterator>
public typealias SubSequence = AnySequence<Iterator.Element>
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
}
public func makeIterator() -> Iterator {
return ZipGenerator3(a.makeIterator(), b.makeIterator(), c.makeIterator())
}
}
// Iterator that creates tuples of values from three other generators
public struct ZipGenerator3<A: IteratorProtocol,
B: IteratorProtocol,
C: IteratorProtocol>: IteratorProtocol {
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
}
mutating public func next() -> (A.Element, B.Element, C.Element)? {
switch (a.next(), b.next(), c.next()) {
case let (.some(aValue), .some(bValue), .some(cValue)):
return (aValue, bValue, cValue)
default:
return nil
}
}
}
func zipWith
<S1: Sequence, S2: Sequence, S3: Sequence, T>
(_ s1: S1, _ s2: S2, _ s3: S3, _ combine: (S1.Iterator.Element,
S2.Iterator.Element,
S3.Iterator.Element) -> T) -> [T] {
return zip3(s1,s2,s3).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.Iterator.Element == Element {
var gen = seq.makeIterator()
while let (k, v) = gen.next() {
self[k] = v
}
}
}