Last active
August 29, 2015 14:12
-
-
Save airspeedswift/3675952127ee775551b0 to your computer and use it in GitHub Desktop.
Converting a dictionary of [key : [values]] to a an array of dictionaries [ [key:value] ] using zipWith
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// from http://stackoverflow.com/questions/27635981/transform-from-dictionary-to-array-in-swift-without-a-for-loop | |
// | |
// 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"]] | |
// --- Begin helpers: zip3, zipWith and Dictionary init from pairs | |
// This version of zip3 taken from Kris Johnson's version here: https://gist.github.com/kristopherjohnson/04dbc470e17f67f836a2 | |
public func zip3<A: SequenceType, B: SequenceType, C: SequenceType>(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: SequenceType, B: SequenceType, C: SequenceType>: SequenceType { | |
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 generate() -> ZipGenerator3<A.Generator, B.Generator, C.Generator> { | |
return ZipGenerator3(a.generate(), b.generate(), c.generate()) | |
} | |
} | |
// Generator that creates tuples of values from three other generators | |
public struct ZipGenerator3<A: GeneratorType, B: GeneratorType, C: GeneratorType>: GeneratorType { | |
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: SequenceType, S2: SequenceType, S3: SequenceType, T> | |
(s1: S1, s2: S2, s3: S3, combine: (S1.Generator.Element,S2.Generator.Element,S3.Generator.Element) -> T) | |
-> [T] { | |
return map(zip3(s1,s2,s3),combine) | |
} | |
extension Dictionary { | |
/// Construct from an arbitrary sequence with elements of the tupe `(Key,Value)` | |
init<S: SequenceType | |
where S.Generator.Element == Element> | |
(_ seq: S) { | |
self.init() | |
self.merge(seq) | |
} | |
/// Merge a sequence of `(Key,Value)` tuples into the dictionary | |
mutating func merge<S: SequenceType | |
where S.Generator.Element == Element> | |
(seq: S) { | |
var gen = seq.generate() | |
while let (k: Key, v: Value) = gen.next() { | |
self[k] = v | |
} | |
} | |
} | |
--- end helpers | |
let returnedFromServer = [ | |
"title" : ["abc", "def"], | |
"time" : ["1234", "5678", "0123"], | |
"content":["qwerty", "asdfg", "zxcvb"] | |
] | |
let pairs = map(returnedFromServer) { (key,value) in map(value) { (key, $0) } } | |
// todo: a version of zipWith that takes a sequence of sequences | |
// (would have the downside of needing key and value in this case to be same type) | |
let inverted = zipWith(pairs[0],pairs[1],pairs[2]) { [$0] + [$1] + [$2] } | |
let arrayOfDicts = inverted.map { Dictionary($0) } | |
println(arrayOfDicts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment