-- Converts a list of key/values into a map, aggregating values
-- e.g. [(1, "one"), (2, "two"), (1, "uno")] -> Map {1: ["one", "uno"], 2: ["two"]}
keyValuesToMap
:: ( Eq k
, Ord k
, Ord v
) => [ ( k
, v
) ] -> M
. Map k
[ v
] keyValuesToMap = M. fromList . groupValues
where
groupValues
:: ( Eq k
, Ord k
, Ord v
) => [ ( k
, v
) ] -> [ ( k
, [ v
] ) ] groupValues
= map foldValues
. groupBy
( \
( x
, _ ) ( y
, _ ) -> x
== y
) . sort
-- Combines values of the same key into a list
-- e.g. [(1, 2), (1, 4), (1, 5)] -> (1, [2, 4, 5])
-- Precondition: the key must be the same for all values in the input list
foldValues
:: ( Eq k
, Ord k
, Ord v
) => [ ( k
, v
) ] -> ( k
, [ v
] ) foldValues xs
= foldr accumulateSameKeyValues
( key
, [ ] ) xs
where
accumulateSameKeyValues
:: ( Eq k
, Ord k
, Ord v
) => ( k
, v
) -> ( k
, [ v
] ) -> ( k
, [ v
] ) accumulateSameKeyValues ( key1, value) ( key2, values)
| key1 == key2 = ( key1, value:values)
LS0gQ29udmVydHMgYSBsaXN0IG9mIGtleS92YWx1ZXMgaW50byBhIG1hcCwgYWdncmVnYXRpbmcgdmFsdWVzCi0tIGUuZy4gWygxLCAib25lIiksICgyLCAidHdvIiksICgxLCAidW5vIildIC0+IE1hcCB7MTogWyJvbmUiLCAidW5vIl0sIDI6IFsidHdvIl19IAprZXlWYWx1ZXNUb01hcCA6OiAoRXEgaywgT3JkIGssIE9yZCB2KSA9PiBbKGssIHYpXSAtPiBNLk1hcCBrIFt2XQprZXlWYWx1ZXNUb01hcCA9IE0uZnJvbUxpc3QgLiBncm91cFZhbHVlcwogICAgd2hlcmUKICAgICAgICBncm91cFZhbHVlcyA6OiAoRXEgaywgT3JkIGssIE9yZCB2KSA9PiBbKGssIHYpXSAtPiBbKGssIFt2XSldCiAgICAgICAgZ3JvdXBWYWx1ZXMgPSBtYXAgZm9sZFZhbHVlcyAuIGdyb3VwQnkgKFwoeCwgXykgKHksIF8pIC0+IHggPT0geSkgLiBzb3J0IAoKICAgICAgICAtLSBDb21iaW5lcyB2YWx1ZXMgb2YgdGhlIHNhbWUga2V5IGludG8gYSBsaXN0CiAgICAgICAgLS0gZS5nLiBbKDEsIDIpLCAoMSwgNCksICgxLCA1KV0gLT4gKDEsIFsyLCA0LCA1XSkgCiAgICAgICAgLS0gUHJlY29uZGl0aW9uOiB0aGUga2V5IG11c3QgYmUgdGhlIHNhbWUgZm9yIGFsbCB2YWx1ZXMgaW4gdGhlIGlucHV0IGxpc3QKICAgICAgICBmb2xkVmFsdWVzIDo6IChFcSBrLCBPcmQgaywgT3JkIHYpID0+IFsoaywgdildIC0+IChrLCBbdl0pCiAgICAgICAgZm9sZFZhbHVlcyB4cyA9IGZvbGRyIGFjY3VtdWxhdGVTYW1lS2V5VmFsdWVzIChrZXksIFtdKSB4cwogICAgICAgICAgICB3aGVyZQogICAgICAgICAgICAgICAga2V5ID0gZnN0IC4gaGVhZCAkIHhzCgogICAgICAgICAgICAgICAgYWNjdW11bGF0ZVNhbWVLZXlWYWx1ZXMgOjogKEVxIGssIE9yZCBrLCBPcmQgdikgPT4gKGssIHYpIC0+IChrLCBbdl0pIC0+IChrLCBbdl0pCiAgICAgICAgICAgICAgICBhY2N1bXVsYXRlU2FtZUtleVZhbHVlcyAoa2V5MSwgdmFsdWUpIChrZXkyLCB2YWx1ZXMpCiAgICAgICAgICAgICAgICAgICAgfCBrZXkxID09IGtleTIgPSAoa2V5MSwgdmFsdWU6dmFsdWVzKQogICAgICAgICAgICAgICAgICAgIHwgb3RoZXJ3aXNlID0gZXJyb3IgIkNhbm5vdCBncm91cCB2YWx1ZXMgZm9yIGRpZmZlcmVudCBrZXlzLiI=