mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
147 lines
3.5 KiB
Swift
147 lines
3.5 KiB
Swift
// 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
|
|
}
|
|
}
|
|
}
|