Skip to content

Instantly share code, notes, and snippets.

@pyrtsa
Created October 4, 2014 13:17
Show Gist options
  • Save pyrtsa/add3efbef6384e5ec3b2 to your computer and use it in GitHub Desktop.
Save pyrtsa/add3efbef6384e5ec3b2 to your computer and use it in GitHub Desktop.
Grouping the elements of a sequence by a key function. (This may not be the fastest implementation out there.)
func groupBy<C: CollectionType, K: Hashable>
(xs: C, key: C.Generator.Element -> K) -> [K:[C.Generator.Element]]
{
var gs: [K:[C.Generator.Element]] = [:]
for x in xs {
let k = key(x)
var ys = gs[k] ?? []
ys.append(x)
gs.updateValue(ys, forKey: k)
}
return gs
}
func isEven<T: protocol<IntegerArithmeticType, IntegerLiteralConvertible>>(n: T) -> Bool { return n % 2 == 0 }
func isOdd <T: protocol<IntegerArithmeticType, IntegerLiteralConvertible>>(n: T) -> Bool { return n % 2 != 0 }
groupBy([0,1,0,3,4,2,2,0], isEven) //=> [false: [1, 3], true: [0, 0, 4, 2, 2, 0]]
groupBy([0,1,0,3,4,2,2,0]) {$0 % 3} //=> [2: [2, 2], 0: [0, 0, 3, 0], 1: [1, 4]]
@pyrtsa
Copy link
Author

pyrtsa commented Oct 4, 2014

I couldn't find a good way to perform updates in-place to the arrays already contained in the dictionary. Maybe something like this might work:

let k = key(x)
var ys = gs.updateValue([], forKey: k) ?? [] // move array out of the dictionary, or create new
ys.append(x)
gs.updateValue(ys, forKey: k) // move back in (and ignore the placeholder)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment