1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
// 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 let benchmarks = [
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
}
}
check(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
}
}
}
|