From d517c8736ddaccfb85e1c00b347eadec81dd1310 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Thu, 9 Nov 2017 16:54:31 +0100
Subject: [PATCH] added data/util/group-by

---
 src/mol-data/util/grouping.ts | 47 +++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 src/mol-data/util/grouping.ts

diff --git a/src/mol-data/util/grouping.ts b/src/mol-data/util/grouping.ts
new file mode 100644
index 000000000..213f3cf54
--- /dev/null
+++ b/src/mol-data/util/grouping.ts
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+export interface Grouping<V, K> {
+    keys: ReadonlyArray<K>,
+    groups: ReadonlyArray<ReadonlyArray<V>>
+}
+
+class GroupingImpl<K, V> {
+    private byKey = new Map<K, V[]>();
+    readonly keys: K[] = [];
+    readonly groups: V[][] = [];
+
+    add(a: V) {
+        const key = this.getKey(a) as any;
+        if (!!this.byKey.has(key)) {
+            const group = this.byKey.get(key)!;
+            group[group.length] = a;
+        } else {
+            const group = [a];
+            this.byKey.set(key, group);
+            this.keys[this.keys.length] = key;
+            this.groups[this.groups.length] = group;
+        }
+    }
+
+    getGrouping(): Grouping<V, K> {
+        return { keys: this.keys, groups: this.groups };
+    }
+
+    constructor(private getKey: (v: V) => K) { }
+}
+
+export function Grouper<V, K>(getKey: (x: V) => K) {
+    return new GroupingImpl<K, V>(getKey);
+}
+
+function groupBy<V, K>(values: ArrayLike<V>, getKey: (x: V) => K) {
+    const gs = Grouper(getKey);
+    for (let i = 0, _i = values.length; i < _i; i++) gs.add(values[i]);
+    return gs.getGrouping();
+}
+
+export default groupBy;
\ No newline at end of file
-- 
GitLab