回答編集履歴
27
テキスト修正
test
CHANGED
@@ -266,7 +266,7 @@
|
|
266
266
|
|
267
267
|
|
268
268
|
|
269
|
-
アルゴリズムとしては、`getUnique8` を拝借し、比較対象として、0以上の整数として設定される id(`
|
269
|
+
アルゴリズムとしては、`getUnique8` を拝借し、比較対象として、0以上の整数として設定される id(=`1000 * x + y`) を使うコードです。
|
270
270
|
|
271
271
|
|
272
272
|
|
26
テキスト修正
test
CHANGED
@@ -356,7 +356,7 @@
|
|
356
356
|
|
357
357
|
|
358
358
|
|
359
|
-
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id`プロパティ のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。その結果、
|
359
|
+
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id`プロパティ のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。その結果、うまく大小関係を定義できれば、`getUnique8`をベースとした速いコードを書くことができます。
|
360
360
|
|
361
361
|
|
362
362
|
|
25
テキスト修正
test
CHANGED
@@ -356,7 +356,7 @@
|
|
356
356
|
|
357
357
|
|
358
358
|
|
359
|
-
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id`プロパティ のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。
|
359
|
+
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id`プロパティ のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。その結果、もし(運良く)大小関係を定義できれば、`getUnique8`をベースとした速いコードを書くことができます。
|
360
360
|
|
361
361
|
|
362
362
|
|
24
テキスト修正
test
CHANGED
@@ -360,4 +360,4 @@
|
|
360
360
|
|
361
361
|
|
362
362
|
|
363
|
-
※このような「そのオブジェクトの値を表すプリミティブ値を返す」ために、対象とするオブジェクト群専用の [valueOf()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) メソッドが定義される場合があります。
|
363
|
+
(※参考:このような「そのオブジェクトの値を表すプリミティブ値を返す」ために、対象とするオブジェクト群専用の [valueOf()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) メソッドが定義される場合があります。)
|
23
テキスト修正
test
CHANGED
@@ -356,7 +356,7 @@
|
|
356
356
|
|
357
357
|
|
358
358
|
|
359
|
-
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id` のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。
|
359
|
+
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id`プロパティ のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。
|
360
360
|
|
361
361
|
|
362
362
|
|
22
テキスト修正
test
CHANGED
@@ -340,7 +340,7 @@
|
|
340
340
|
|
341
341
|
```
|
342
342
|
|
343
|
-
という型を満たしているという前提が明らかになっていれば、これを元に、問題の対象範囲に出現するオブジェクトの集合が全順序集合になるような、何らかの大小関係
|
343
|
+
という型を満たしているという前提が明らかになっていれば、これを元に、問題の対象範囲に出現するオブジェクトの集合が全順序集合になるような、何らかの大小関係(つまり、ソート結果が一意になる比較関数)を定義できるかどうか検討することができて、もし(運良く)大小関係を定義できれば、Set や Map を使わない `getUnique13`やその元となっている `getUnique8`のようなコードを書けますが、もし、`a` や `b` の要素として入ってくるオブジェクトの型が不明という状況、すなわち、ご質問のタイトルにある
|
344
344
|
|
345
345
|
「二つの配列、それぞれに含まれるユニークな値をできるだけ高速に抽出する方法」
|
346
346
|
|
21
テキスト修正
test
CHANGED
@@ -340,7 +340,11 @@
|
|
340
340
|
|
341
341
|
```
|
342
342
|
|
343
|
-
という型を満たしているという前提が明らかになっていれば、これを元に、問題の対象範囲に出現するオブジェクトの集合が全順序集合になるような、何らかの大小関係を定義できて(つまり、ソート結果が一意な
|
343
|
+
という型を満たしているという前提が明らかになっていれば、これを元に、問題の対象範囲に出現するオブジェクトの集合が全順序集合になるような、何らかの大小関係を定義できて(つまり、ソート結果が一意な大小関係を定義できて)、Set や Map を使わない `getUnique13`やその元となっている `getUnique8`のようなコードを書けますが、もし、`a` や `b` の要素として入ってくるオブジェクトの型が不明という状況、すなわち、ご質問のタイトルにある
|
344
|
+
|
345
|
+
「二つの配列、それぞれに含まれるユニークな値をできるだけ高速に抽出する方法」
|
346
|
+
|
347
|
+
の一般解を求めようとすると、この回答の冒頭に挙げた
|
344
348
|
|
345
349
|
```javascript
|
346
350
|
|
@@ -352,4 +356,8 @@
|
|
352
356
|
|
353
357
|
|
354
358
|
|
355
|
-
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの比較関数、あるいは比較可能な(今回の `id` のような)そのオブジェクトのプリミティブ値を導入でき
|
359
|
+
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの大小比較関数、あるいは大小の比較が可能な(今回の `id` のような)そのオブジェクトのプリミティブ値(※)を導入できるかどうか検討することが、ある型を要素とする配列の差分抽出には優先順位の高いタスクかなと思われました。
|
360
|
+
|
361
|
+
|
362
|
+
|
363
|
+
※このような「そのオブジェクトの値を表すプリミティブ値を返す」ために、対象とするオブジェクト群専用の [valueOf()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) メソッドが定義される場合があります。
|
20
テキスト修正
test
CHANGED
@@ -323,3 +323,33 @@
|
|
323
323
|
|
324
324
|
|
325
325
|
参考になれば幸いです。
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
|
330
|
+
|
331
|
+
### 所感
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
ご質問のサンプルにあるように、配列`a` 配列 `b` ともにその要素はすべて
|
336
|
+
|
337
|
+
```typescript
|
338
|
+
|
339
|
+
{ x: number; y: number }
|
340
|
+
|
341
|
+
```
|
342
|
+
|
343
|
+
という型を満たしているという前提が明らかになっていれば、これを元に、問題の対象範囲に出現するオブジェクトの集合が全順序集合になるような、何らかの大小関係を定義できて(つまり、ソート結果が一意な比較関数を定義できて)、Set や Map を使わない `getUnique13`やその元となっている `getUnique8`のようなコードを書けますが、もし、`a` や `b` の要素として入ってくるオブジェクトの型が不明という状況だと、この回答の冒頭に挙げた
|
344
|
+
|
345
|
+
```javascript
|
346
|
+
|
347
|
+
const getUnique = (a,b) => _.differenceWith(a, b, _.isEqual);
|
348
|
+
|
349
|
+
```
|
350
|
+
|
351
|
+
のような時間のかかるコードに頼らざるを得なくなるのかなという気はいたします。
|
352
|
+
|
353
|
+
|
354
|
+
|
355
|
+
とはいえ、実際の何らかの問題領域においては、配列要素となるオブジェクトの型は何らか特定できるものなので、その型情報から、問題領域に出現し得るオブジェクト群が全順序を満たすような何らかの比較関数、あるいは比較可能な(今回の `id` のような)そのオブジェクトのプリミティブ値を導入できないかどうか検討することが、(ある型を要素とする)配列の差分抽出には優先順位の高いタスクかなと思われました。
|
19
テキスト修正
test
CHANGED
@@ -292,11 +292,11 @@
|
|
292
292
|
|
293
293
|
for (let iA=0, iB=0; iA < lenA || iB < lenB; ) {
|
294
294
|
|
295
|
-
if (iB
|
295
|
+
if (iB === lenB || iA < lenA && a[iA].id < b[iB].id) {
|
296
296
|
|
297
297
|
onlyA.push(a[iA ++]);
|
298
298
|
|
299
|
-
} else if (iA
|
299
|
+
} else if (iA === lenA || iB < lenB && b[iB].id < a[iA].id) {
|
300
300
|
|
301
301
|
onlyB.push(b[iB ++]);
|
302
302
|
|
@@ -318,7 +318,7 @@
|
|
318
318
|
|
319
319
|
```
|
320
320
|
|
321
|
-
- ** getUnique13:** [https://jsfiddle.net/jun68ykt/h2ydp9sj/1
|
321
|
+
- ** getUnique13:** [https://jsfiddle.net/jun68ykt/h2ydp9sj/11/](https://jsfiddle.net/jun68ykt/h2ydp9sj/11/)
|
322
322
|
|
323
323
|
|
324
324
|
|
18
テキスト修正
test
CHANGED
@@ -262,4 +262,64 @@
|
|
262
262
|
|
263
263
|
|
264
264
|
|
265
|
+
### 追記 - getUnique13
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
アルゴリズムとしては、`getUnique8` を拝借し、比較対象として、0以上の整数として設定される id(`const id = 1000 * x + y;`) を使うコードです。
|
270
|
+
|
271
|
+
|
272
|
+
|
273
|
+
```javascript
|
274
|
+
|
275
|
+
function getUnique13(a, b) {
|
276
|
+
|
277
|
+
const lenA = a.length,
|
278
|
+
|
279
|
+
lenB = b.length,
|
280
|
+
|
281
|
+
onlyA = [],
|
282
|
+
|
283
|
+
onlyB = [];
|
284
|
+
|
285
|
+
|
286
|
+
|
287
|
+
a.sort((e1, e2) => e1.id - e2.id);
|
288
|
+
|
289
|
+
b.sort((e1, e2) => e1.id - e2.id);
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
for (let iA=0, iB=0; iA < lenA || iB < lenB; ) {
|
294
|
+
|
295
|
+
if (iB >= lenB || iA < lenA && a[iA].id < b[iB].id) {
|
296
|
+
|
297
|
+
onlyA.push(a[iA ++]);
|
298
|
+
|
299
|
+
} else if (iA >= lenA || iB < lenB && b[iB].id < a[iA].id) {
|
300
|
+
|
301
|
+
onlyB.push(b[iB ++]);
|
302
|
+
|
303
|
+
} else {
|
304
|
+
|
305
|
+
iA ++;
|
306
|
+
|
307
|
+
iB ++;
|
308
|
+
|
309
|
+
}
|
310
|
+
|
311
|
+
}
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
return [onlyA, onlyB];
|
316
|
+
|
317
|
+
}
|
318
|
+
|
319
|
+
```
|
320
|
+
|
321
|
+
- ** getUnique13:** [https://jsfiddle.net/jun68ykt/h2ydp9sj/10/](https://jsfiddle.net/jun68ykt/h2ydp9sj/10/)
|
322
|
+
|
323
|
+
|
324
|
+
|
265
|
-
|
325
|
+
参考になれば幸いです。
|
17
テキスト修正
test
CHANGED
@@ -36,7 +36,7 @@
|
|
36
36
|
|
37
37
|
|
38
38
|
|
39
|
-
上記ではlodashを使った汎用的なコードを挙げましたが、コメントから頂きましたjsFiddleのテストコードによって生成されるオブジェクトの配列を処理することに特化し
|
39
|
+
上記ではlodashを使った汎用的なコードを挙げましたが、コメントから頂きましたjsFiddleのテストコードによって生成されるオブジェクトの配列を処理することに特化したコードも考えてみました。以下の `getUnique10` になります。
|
40
40
|
|
41
41
|
|
42
42
|
|
16
テキスト修正
test
CHANGED
@@ -258,4 +258,8 @@
|
|
258
258
|
|
259
259
|
|
260
260
|
|
261
|
+
![イメージ説明](a7bb4474530734b107acd6d278265e54.png)
|
262
|
+
|
263
|
+
|
264
|
+
|
261
265
|
以上、参考になれば幸いです。
|
15
テキスト修正
test
CHANGED
@@ -182,7 +182,71 @@
|
|
182
182
|
|
183
183
|
|
184
184
|
|
185
|
-
先述の `getUnique11` のループで使っている、 `for ・・・ of` および `filter` を、 (ofなしの)`for`文に変更した、 `getUnique12` を作成しました。
|
185
|
+
先述の `getUnique11` のループで使っている、 `for ・・・ of` および `filter` を、 (ofなしの)`for`文に変更した、 `getUnique12` を作成しました。
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
```javascript
|
190
|
+
|
191
|
+
function getUnique12(a, b) {
|
192
|
+
|
193
|
+
const set = new Set();
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
const lenA = a.length;
|
198
|
+
|
199
|
+
const lenB = b.length;
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
for (let i=0; i < lenA; ++ i)
|
204
|
+
|
205
|
+
set.add(a[i].id);
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
for (let i=0; i < lenB; ++ i)
|
210
|
+
|
211
|
+
set.add(~b[i].id);
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
const onlyA = [];
|
216
|
+
|
217
|
+
for (let i=0; i < lenA; ++ i) {
|
218
|
+
|
219
|
+
if(!set.has(~a[i].id))
|
220
|
+
|
221
|
+
onlyA.push(a[i]);
|
222
|
+
|
223
|
+
}
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
const onlyB = [];
|
228
|
+
|
229
|
+
for (let i=0; i < lenB; ++ i) {
|
230
|
+
|
231
|
+
if(!set.has(b[i].id))
|
232
|
+
|
233
|
+
onlyB.push(b[i]);
|
234
|
+
|
235
|
+
}
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
return [onlyA, onlyB];
|
240
|
+
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
```
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
`getUnique11`との比較をするための jsFiddleが下記です。
|
186
250
|
|
187
251
|
|
188
252
|
|
14
テキスト修正
test
CHANGED
@@ -92,7 +92,7 @@
|
|
92
92
|
|
93
93
|
|
94
94
|
|
95
|
-
前掲の `getUnique10` の改良案を挙げます。この改良案は、(コメントに
|
95
|
+
前掲の `getUnique10` の改良案を挙げます。この改良案は、(2019/11/14 21:10のコメントに書いたとおり、) 下記
|
96
96
|
|
97
97
|
|
98
98
|
|
13
テキスト修正
test
CHANGED
@@ -150,7 +150,7 @@
|
|
150
150
|
|
151
151
|
```
|
152
152
|
|
153
|
-
`getUnique10` では 2個の Set を使っていましたが、上記の `getUnique11` では、1個で済ませるようにして、Set 1個分のコンストラクタ `new Set()` の時間を減らすことを狙っています。Setを1個にした替わりに、b の要素の id をSet にaddするときに、
|
153
|
+
`getUnique10` では 2個の Set を使っていましたが、上記の `getUnique11` では、1個で済ませるようにして、Set 1個分のコンストラクタ `new Set()` の時間を減らすことを狙っています。Setを1個にした替わりに、b の要素の id をSet にaddするときに、a の要素のidと被らない値に変換する必要がありますが、その変換のために、(整数に対する演算として速いことが期待できる)ビット反転 `~` を使っています。
|
154
154
|
|
155
155
|
|
156
156
|
|
12
テキスト修正
test
CHANGED
@@ -92,7 +92,7 @@
|
|
92
92
|
|
93
93
|
|
94
94
|
|
95
|
-
前掲の `getUnique10` の改良案を挙げます。この改良案は、コメントには既に書きました、下記
|
95
|
+
前掲の `getUnique10` の改良案を挙げます。この改良案は、(コメントには既に書きましたが、) 下記
|
96
96
|
|
97
97
|
|
98
98
|
|
11
テキスト修正
test
CHANGED
@@ -78,7 +78,7 @@
|
|
78
78
|
|
79
79
|
|
80
80
|
|
81
|
-
- **getUnique
|
81
|
+
- **getUnique7 vs getUnique10:** [https://jsfiddle.net/jun68ykt/b501gqpj/1/](https://jsfiddle.net/jun68ykt/b501gqpj/1/)
|
82
82
|
|
83
83
|
|
84
84
|
|
10
テキスト修正
test
CHANGED
@@ -114,7 +114,7 @@
|
|
114
114
|
|
115
115
|
```
|
116
116
|
|
117
|
-
のようなコードによって、 `id` に整数の値を設定することが前提になります。`getUnique11` は以下です。
|
117
|
+
のようなコードによって、 `id` に0以上の整数の値を設定することが前提になります。`getUnique11` は以下です。
|
118
118
|
|
119
119
|
|
120
120
|
|
9
テキスト修正
test
CHANGED
@@ -114,7 +114,7 @@
|
|
114
114
|
|
115
115
|
```
|
116
116
|
|
117
|
-
のようなコードによって、 `id` に数値を設定することが前提になります。`getUnique11` は以下です。
|
117
|
+
のようなコードによって、 `id` に整数の値を設定することが前提になります。`getUnique11` は以下です。
|
118
118
|
|
119
119
|
|
120
120
|
|
8
テキスト修正
test
CHANGED
@@ -36,7 +36,7 @@
|
|
36
36
|
|
37
37
|
|
38
38
|
|
39
|
-
上記ではlodashを使った汎用的なコードを挙げましたが、コメントから頂きました
|
39
|
+
上記ではlodashを使った汎用的なコードを挙げましたが、コメントから頂きましたjsFiddleのテストコードによって生成されるオブジェクトの配列を処理することに特化して、なるべく高速に処理するコードも考えてみました。以下の `getUnique10` になります。
|
40
40
|
|
41
41
|
|
42
42
|
|
7
テキスト修正
test
CHANGED
@@ -36,7 +36,7 @@
|
|
36
36
|
|
37
37
|
|
38
38
|
|
39
|
-
lodashを使
|
39
|
+
上記ではlodashを使った汎用的なコードを挙げましたが、コメントから頂きました、jsFiddleのテストコードによって生成させるオブジェクトの配列を処理することに特化して、なるべく高速に処理するコードも考えてみました。以下の `getUnique10` になります。
|
40
40
|
|
41
41
|
|
42
42
|
|
@@ -74,15 +74,15 @@
|
|
74
74
|
|
75
75
|
|
76
76
|
|
77
|
-
|
77
|
+
この `getUnique10` を試すコードを以下の jsFiddle に作成しました。
|
78
78
|
|
79
79
|
|
80
80
|
|
81
|
-
- **
|
81
|
+
- **getUnique10 vs getUnique7:** [https://jsfiddle.net/jun68ykt/b501gqpj/1/](https://jsfiddle.net/jun68ykt/b501gqpj/1/)
|
82
82
|
|
83
83
|
|
84
84
|
|
85
|
-
|
85
|
+
上記は、コメントからご教示いただきました、 [https://jsfiddle.net/e9a5kvw2/](https://jsfiddle.net/e9a5kvw2/) を Forkして、テスト対象として`getUnique10` を追加したものです。
|
86
86
|
|
87
87
|
|
88
88
|
|
6
テキスト修正
test
CHANGED
@@ -178,4 +178,20 @@
|
|
178
178
|
|
179
179
|
|
180
180
|
|
181
|
+
### 追記 - getUnique12
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
先述の `getUnique11` のループで使っている、 `for ・・・ of` および `filter` を、 (ofなしの)`for`文に変更した、 `getUnique12` を作成しました。`getUnique11`との比較をするための jsFiddleが下記です。
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
- **getUnique11 vs getUnique12:** [https://jsfiddle.net/jun68ykt/ajtnd5wm/13/](https://jsfiddle.net/jun68ykt/ajtnd5wm/13/)
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
当方の環境では、`getUnique12` のほうが数ミリ〜10ミリ秒程度、短くなる結果を確認しています。
|
194
|
+
|
195
|
+
|
196
|
+
|
181
197
|
以上、参考になれば幸いです。
|
5
テキスト修正
test
CHANGED
@@ -92,7 +92,7 @@
|
|
92
92
|
|
93
93
|
|
94
94
|
|
95
|
-
|
95
|
+
前掲の `getUnique10` の改良案を挙げます。この改良案は、コメントには既に書きました、下記
|
96
96
|
|
97
97
|
|
98
98
|
|
4
テキスト修正
test
CHANGED
@@ -92,7 +92,7 @@
|
|
92
92
|
|
93
93
|
|
94
94
|
|
95
|
-
上記の `getUnique10` の改良案を挙げます。
|
95
|
+
上記の `getUnique10` の改良案を挙げます。この改良案は、コメントには既に書きました、下記
|
96
96
|
|
97
97
|
|
98
98
|
|
@@ -114,7 +114,7 @@
|
|
114
114
|
|
115
115
|
```
|
116
116
|
|
117
|
-
にて、 `id`
|
117
|
+
のようなコードによって、 `id` に数値を設定することが前提になります。`getUnique11` は以下です。
|
118
118
|
|
119
119
|
|
120
120
|
|
3
テキスト修正
test
CHANGED
@@ -150,7 +150,7 @@
|
|
150
150
|
|
151
151
|
```
|
152
152
|
|
153
|
-
`getUnique10` では 2個の Set を使っていましたが、上記の `getUnique11` では、1個で済ませるようにして、Set 1個分のコンストラクタの時間を減らすことを狙っています。Setを1個にした替わりに、b の要素の id をSet にaddするときに、それが b の要素のid であることが分かるように、ビット反転した値を add しています。
|
153
|
+
`getUnique10` では 2個の Set を使っていましたが、上記の `getUnique11` では、1個で済ませるようにして、Set 1個分のコンストラクタ `new Set()` の時間を減らすことを狙っています。Setを1個にした替わりに、b の要素の id をSet にaddするときに、それが b の要素のid であることが分かるように、ビット反転した値を add しています。
|
154
154
|
|
155
155
|
|
156
156
|
|
2
テキスト修正
test
CHANGED
@@ -88,4 +88,94 @@
|
|
88
88
|
|
89
89
|
|
90
90
|
|
91
|
+
### 追記 - getUnique11
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
上記の `getUnique10` の改良案を挙げます。ただしこの改良案は、コメントに書いたように、下記
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
```javascript
|
100
|
+
|
101
|
+
const num = 1000;
|
102
|
+
|
103
|
+
for (let i = 0; i < num; i++) {
|
104
|
+
|
105
|
+
const x = i;
|
106
|
+
|
107
|
+
const y = Math.floor(Math.random() * num);
|
108
|
+
|
109
|
+
// const id = `${x}:${y}`
|
110
|
+
|
111
|
+
const id = 1000 * x + y;
|
112
|
+
|
113
|
+
・・・
|
114
|
+
|
115
|
+
```
|
116
|
+
|
117
|
+
にて、 `id` を数値として設定することが前提になります。`getUnique11` は以下です。
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
```javascript
|
122
|
+
|
123
|
+
function getUnique11(a, b) {
|
124
|
+
|
125
|
+
const set = new Set();
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
for (let e of a)
|
130
|
+
|
131
|
+
set.add(e.id);
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
for (let e of b)
|
136
|
+
|
137
|
+
set.add(~e.id);
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
const onlyA = a.filter(e => !set.has(~e.id));
|
142
|
+
|
143
|
+
const onlyB = b.filter(e => !set.has(e.id));
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
return [onlyA, onlyB];
|
148
|
+
|
149
|
+
}
|
150
|
+
|
151
|
+
```
|
152
|
+
|
153
|
+
`getUnique10` では 2個の Set を使っていましたが、上記の `getUnique11` では、1個で済ませるようにして、Set 1個分のコンストラクタの時間を減らすことを狙っています。Setを1個にした替わりに、b の要素の id をSet にaddするときに、それが b の要素のid であることが分かるように、ビット反転した値を add しています。
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
以下にて、 `getUnique10` と `getUnique11` とを比較できます。
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
- **getUnique10 vs getUnique11:** [https://jsfiddle.net/jun68ykt/ajtnd5wm/5/](https://jsfiddle.net/jun68ykt/ajtnd5wm/5/)
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
当方の環境(PC: Macbook Pro(Core i7 2.8GHz), ブラウザ: Chrome バージョン: 78.0.3904.97)では、以下
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
![イメージ説明](09d6a8732bfc89bee7c8ea993573d46a.png)
|
170
|
+
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
のように、`getUnique11`の所要時間のほうが、`getUnique10` の所要時間よりも短くなる結果を得ています。
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
|
91
181
|
以上、参考になれば幸いです。
|
1
テキスト修正
test
CHANGED
@@ -26,4 +26,66 @@
|
|
26
26
|
|
27
27
|
|
28
28
|
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
### 追記 - getUnique10
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
lodashを使わずに、なるべく高速に処理するコードも考えてみました。以下の `getUnique10` になります。
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
```javascript
|
44
|
+
|
45
|
+
function getUnique10(a, b) {
|
46
|
+
|
47
|
+
const [setA, setB] = [new Set(), new Set()];
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
for (let e of a)
|
52
|
+
|
53
|
+
setA.add(e.id);
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
for (let e of b)
|
58
|
+
|
59
|
+
setB.add(e.id);
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
const onlyA = a.filter(e => !setB.has(e.id));
|
64
|
+
|
65
|
+
const onlyB = b.filter(e => !setA.has(e.id));
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
return [onlyA, onlyB]
|
70
|
+
|
71
|
+
}
|
72
|
+
|
73
|
+
```
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
上記の `getUnique10` を試すコードを以下の jsFiddle に作成しました。
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
- **動作確認用 jsFiddle :** [https://jsfiddle.net/jun68ykt/b501gqpj/1/](https://jsfiddle.net/jun68ykt/b501gqpj/1/)
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
これは、コメントからご教示いただきました、 [https://jsfiddle.net/e9a5kvw2/](https://jsfiddle.net/e9a5kvw2/) を Forkして、テスト対象として`getUnique10` を追加したものです。
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
|
29
91
|
以上、参考になれば幸いです。
|