teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

テキスト修正

2020/08/28 01:00

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -51,7 +51,7 @@
51
51
  ```javascript
52
52
  `${e.id}${e.name}${e.course_id}`
53
53
  ```
54
- は使えないので、オブジェクトの値として、他の作り方を検討する必要があります。このご質問のような課題の解決の際に、各オブジェクトの等値性を判定するための値(言い換えると、各オブジェクトを何らかのクラスのインタンスとして得ることにした場合に、そのクラスの`valueOf`メソッドが返す値)をうまく決められるかどうか、というのがひとつのになります。
54
+ は使えないので、オブジェクトの値(value)別の作り方を検討する必要があります。このご質問のような課題の解決の際に、各オブジェクトの等値性を判定するための値(言い換えると、各オブジェクトを何らかのクラスのインタンスとして得ることにした場合に、そのクラスの`valueOf`メソッドが返す値)をうまく決められるかどうか、というのがひとつの検討事項になります。
55
55
 
56
56
  以上、参考になれば幸いです。
57
57
 

4

テキスト修正

2020/08/28 01:00

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -53,4 +53,9 @@
53
53
  ```
54
54
  は使えないので、オブジェクトの値として、他の作り方を検討する必要があります。このご質問のような課題の解決の際に、各オブジェクトの等値性を判定するための値(言い換えると、各オブジェクトを何らかのクラスのインタンスとして得ることにした場合に、そのクラスの`valueOf`メソッドが返す値)をうまく決められるかどうか、というのがひとつの鍵になります。
55
55
 
56
- 以上、参考になれば幸いです。
56
+ 以上、参考になれば幸いです。
57
+
58
+ ### 追記
59
+
60
+ はじめに挙げた、Set を使うコードのほうで、Setのインスタンスをnewで作るコストが気になるようであれば、Setの替わりにプレーンオブジェクトを使うこともできます。
61
+ - **動作確認用 codepen.io:** [jun68ykt/pen/KKzmGLM](https://codepen.io/jun68ykt/pen/KKzmGLM?editors=0012)

3

テキスト修正

2020/08/28 00:16

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -38,7 +38,7 @@
38
38
  - **動作確認用 codepen.io:** [jun68ykt/pen/RwaVBza](https://codepen.io/jun68ykt/pen/RwaVBza?editors=0012)
39
39
 
40
40
 
41
- ただし、上記はオブジェクトの等値判定に、汎用的な `_.isEqual`を使っているので、やや非効率です。先と同様にオブジェクトの値(value)を定義できるのであれば、オブジェクトの値を取得するメソッド`valueOf`を作っておいて、等値判定のためにこれを利用できます。以下はその例です。
41
+ ただし、上記はオブジェクトの等値判定に、汎用的な `_.isEqual`を使っているところが非効率です。先と同様にオブジェクトの値(value)を定義できるのであれば、オブジェクトの値を取得するメソッド`valueOf`を作っておいて、等値判定のためにこれを利用できます。以下はその例です。
42
42
 
43
43
  ```javascript
44
44
  const valueOf = e => `${e.id}${e.name}${e.course_id}`;

2

テキスト修正

2020/08/27 23:59

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -51,6 +51,6 @@
51
51
  ```javascript
52
52
  `${e.id}${e.name}${e.course_id}`
53
53
  ```
54
- は使えないので、オブジェクトの値として、他の作り方を検討する必要があります。
54
+ は使えないので、オブジェクトの値として、他の作り方を検討する必要があります。このご質問のような課題の解決の際に、各オブジェクトの等値性を判定するための値(言い換えると、各オブジェクトを何らかのクラスのインタンスとして得ることにした場合に、そのクラスの`valueOf`メソッドが返す値)をうまく決められるかどうか、というのがひとつの鍵になります。
55
55
 
56
56
  以上、参考になれば幸いです。

1

テキスト修正

2020/08/27 22:59

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -1,16 +1,56 @@
1
1
  こんにちは
2
2
 
3
- 配列やオブジェクトの操作で便利なライブラリ [lodash](https://lodash.com/) を使った回答になります。
4
-
5
3
  ご質問の題意としては、
6
4
 
7
5
  - 配列`items` の要素のオブジェクトについて、プロパティのすべてが同じ値であるものが二個以上含まれないように、かつ、要素の順番は保存されている配列を `target` に得たい。
8
6
 
9
7
  ということと解釈しました。(この解釈が違っていたら、コメントからお知らせください。)このような`target` は、以下によって得られます。
10
8
 
9
+ ### Set を使用
10
+
11
+ 重複をチェックするために Set を使います。
12
+
13
+ 各オブジェクトの `name` は、アルファベットのみから構成される文字列であると仮定とすると、各オブジェクトの等値性は、`id`, `name`, `course_id` の順に値を連結して得られる文字列を比較すればよいことになります。この文字列を各要素の**値(value)**と呼ぶことにすると、items に出現する各要素の値を、Set に格納していけば、重複チェックの計算量をO(1)で済ませることができます。
14
+
11
15
  ```javascript
16
+ const set = new Set();
17
+
18
+ const target = items.filter(e => {
19
+ const value = `${e.id}${e.name}${e.course_id}`;
20
+ if (set.has(value)) {
21
+ return false;
22
+ } else {
23
+ set.add(value);
24
+ return true;
25
+ }
26
+ });
27
+ ```
28
+ - **動作確認用 codepen.io:** [jun68ykt/pen/poyPOVG](https://codepen.io/jun68ykt/pen/poyPOVG?editors=0012)
29
+
30
+
31
+ ### lodash を使用
32
+
33
+ 配列やオブジェクトの操作で便利なライブラリ [lodash](https://lodash.com/) を使うと以下のように手短かに書けます。
34
+
35
+ ```javascript
12
36
  const target = _.uniqWith(items, _.isEqual);
13
37
  ```
14
38
  - **動作確認用 codepen.io:** [jun68ykt/pen/RwaVBza](https://codepen.io/jun68ykt/pen/RwaVBza?editors=0012)
15
39
 
40
+
41
+ ただし、上記はオブジェクトの等値判定に、汎用的な `_.isEqual`を使っているので、やや非効率です。先と同様にオブジェクトの値(value)を定義できるのであれば、オブジェクトの値を取得するメソッド`valueOf`を作っておいて、等値判定のためにこれを利用できます。以下はその例です。
42
+
43
+ ```javascript
44
+ const valueOf = e => `${e.id}${e.name}${e.course_id}`;
45
+
46
+ const target = _.uniqBy(items, valueOf);
47
+ ```
48
+ - **動作確認用 codepen.io:** [jun68ykt/pen/eYZWLam](https://codepen.io/jun68ykt/pen/eYZWLam?editors=0012)
49
+
50
+ なお、`name` プロパティに、`'9apple'` や `'lemon3'` といったような、数字で始まる、または数字で終わる文字列が出現する可能性があるならば、オブジェクトの等値性を判定する値として、
51
+ ```javascript
52
+ `${e.id}${e.name}${e.course_id}`
53
+ ```
54
+ は使えないので、オブジェクトの値として、他の作り方を検討する必要があります。
55
+
16
- 参考になれば幸いです。
56
+ 以上、参考になれば幸いです。