Przeglądaj źródła

perf(common): Increase perf of `unique` helper by ~1000x

Relates to #1433
Michael Bromley 3 lat temu
rodzic
commit
910adf8494
2 zmienionych plików z 27 dodań i 12 usunięć
  1. 18 0
      packages/common/src/unique.spec.ts
  2. 9 12
      packages/common/src/unique.ts

+ 18 - 0
packages/common/src/unique.spec.ts

@@ -30,4 +30,22 @@ describe('unique()', () => {
     it('works an empty array', () => {
         expect(unique([])).toEqual([]);
     });
+
+    it('perf on primitive array', async () => {
+        const bigArray = Array.from({ length: 50000 }).map(() => Math.random().toString().substr(2, 5));
+        const timeStart = new Date().getTime();
+        unique(bigArray);
+        const timeEnd = new Date().getTime();
+        expect(timeEnd - timeStart).toBeLessThan(100);
+    });
+
+    it('perf on object array', async () => {
+        const bigArray = Array.from({ length: 50000 })
+            .map(() => Math.random().toString().substr(2, 5))
+            .map(id => ({ id }));
+        const timeStart = new Date().getTime();
+        unique(bigArray, 'id');
+        const timeEnd = new Date().getTime();
+        expect(timeEnd - timeStart).toBeLessThan(100);
+    });
 });

+ 9 - 12
packages/common/src/unique.ts

@@ -1,19 +1,16 @@
 /**
+ * @description
  * Returns an array with only unique values. Objects are compared by reference,
  * unless the `byKey` argument is supplied, in which case matching properties will
  * be used to check duplicates
  */
+import { isObject } from './shared-utils';
+
 export function unique<T>(arr: T[], byKey?: keyof T): T[] {
-    return arr.filter((item, index, self) => {
-        return (
-            index ===
-            self.findIndex(i => {
-                if (byKey === undefined) {
-                    return i === item;
-                } else {
-                    return i[byKey] === item[byKey];
-                }
-            })
-        );
-    });
+    if (byKey == null) {
+        return Array.from(new Set(arr));
+    } else {
+        // Based on https://stackoverflow.com/a/58429784/772859
+        return [...new Map(arr.map(item => [item[byKey], item])).values()];
+    }
 }