質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1094閲覧

javascriptの配列の列数が可変のとき、filterで対応できる方法は無いでしょうか?

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2020/02/07 02:19

配列の列数が可変のとき、filterで対応できる方法はないでしょうか?

例えば部屋番号から、合う鍵を探す処理です。
102号室のkeynoを探します。

var result = [{"keyno":"A1","room1":"102","room2":"103"},{"keyno":"B2","room1":"201","room2":"202"}].filter( x=> x.room1 === "102" || x.room2 === "102");

結果は、鍵番号は”A1”でした。

[ { keyno: 'A1', room1: '102', room2: '103' } ]

しかし、部屋数が各階3部屋の場合もあります。部屋数は可変です。

var result = [{"keyno":"A1","room1":"101","room2":"102","room3":"103"},{"keyno":"B2","room1":"201","room2":"202","room3":"203"}].filter( x=> x.room1 === "102" || x.room2 === "102" || x.room3 === "102");

結果は以下です。

[ { keyno: 'A1', room1: '101', room2: '102', room3: '103' } ]

要は、条件部の

x.room1 === "102" || x.room2 === "102" || x.room3 === "102"

の部分が可変です。

ここをうまく対応する記述方法は無いでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/02/07 02:21

そもそも論として、「データ構造自体を変える」のが楽にはなるかと思いますけど、それは無理なのでしょうか。
guest

回答2

0

ベストアンサー

各オブジェクトに対してObject.keysでたどる、という方法が考えられます。

javascript

1.filter(x => Object.keys(x).some(key => /^room/.test(key) && x[key] === "102"))

もっとも、元のデータ構造を変えられるのであればそのほうが望ましいです。

投稿2020/02/07 02:24

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/02/07 06:15

ありがとうございました。 これなら1行で済むので、簡潔に実装できます。
guest

0

状況説明がちょっと足りてなくて、半分程度しか理解出来てませんが

js

1x.room1 === "102" || x.room2 === "102" || x.room3 === "102"

この関数が可変になる、いい感じの関数を流し込みたいということでしょうか?
使い勝手の良い関数さえ準備できれば、keys.filter(fn)というコード一撃で解決出来ますからね。

2段階で引数要求するようにすれば使い回せる関数を準備出来ます。

js

1const keys = [ 2 {"keyno":"A1","room1":"102","room2":"103"}, 3 {"keyno":"B2","room1":"201","room2":"202"}, 4]; 5const isValidKey = (rooms, roomNo, key) => 6 rooms.map(it => key[it]).some(it => it === roomNo); 7const output = it => console.log(it); 8 9keys 10 .filter(isValidKey.bind(null, ['room1', 'room2'], "102")) 11 .forEach(output); 12// {keyno: "A1", room1: "102", room2: "103"}

今回はFn.bindを利用して引数を束縛するという事を行いました
これを部分適用と呼び、これにはいくつかパターンがあります。

こんな風に実行する度に引数を束縛し、引数が3つ揃った瞬間に発火する仕組みを作る事も可能です。

js

1const isValidKey = rooms => roomNo => key => 2 rooms.map(it => key[it]).some(it => it === roomNo); 3 4// 使い方はこのように変化する 5keys 6 .filter(isValidKey(['room1', 'room2'])("102")) 7 .forEach(output); 8// {keyno: "A1", room1: "102", room2: "103"}

最後にroomの名称が可変なのでその場その場で書き換えたくないというなら、
それなりの配列を定義しておきましょうという話になります。

一応鍵の配列から作れそうだったのでそちらも作って終わりにします。
鍵が用意出来るなら一覧も作れるでしょうからね。

js

1// 質問文から弄って、A1の鍵はroom3を、A2の鍵はroom4の情報をもたせている 2const keys = [ 3 {"keyno":"A1","room1":"101","room2":"102","room3":"103"}, 4 {"keyno":"B2","room1":"201","room2":"202","room4":"203"}, 5]; 6const rooms = keys 7 .map(it => Object.keys(it).filter(it => it !== "keyno")) 8 .reduce((arr, it) => [ 9 ...arr, 10 ...it.filter(key => !arr.includes(key)) 11 ]); 12 13console.log(rooms); 14// ["room1", "room2", "room3", "room4"] 15// 重複してないしroom3もroom4も含んでいる配列になった

【おまけ】 データ構造変更の提案

js

1[ 2 {"keyno":"A1","room1":"102","room2":"103"}, 3 {"keyno":"B2","room1":"201","room2":"202"}, 4];

冒頭に存在するコレ、非常に扱いにくいです。
room1とかroom2とか誰が決めたんですか?
1番目ルームなのに102号室だったり、201号室だったりして一貫性がありません。

普通に考えてこうなっているべきです。
A1の鍵で開けられるのは102号室・103号室の2つですよという意味がバシッと通って使いやすくなっています。

js

1[ 2 {keyno:"A1", rooms: ["102", "103"]}, 3 {keyno:"B2", rooms: ["201", "202"]}, 4] 5 .filter(key => key.rooms.includes("102")) 6 .forEach(it => console.log(it)); 7// {keyno: "A1", rooms: ["102", "103"]}

どうしても変更出来ないというのであれば、
こういう風にメインロジックに持ち込みやすい形に整形すると良いでしょう。

js

1const keys = [ 2 {"keyno":"A1","room1":"102","room2":"103"}, 3 {"keyno":"B2","room1":"201","room2":"202"}, 4].map(key => ({ 5 keyno: key.keyno, 6 rooms: Object.keys(key).filter(it => it !== "keyno").map(it => key[it]), 7})); 8console.log(keys); 9// [{keyno: "A1", rooms: ["102", "103"]}, {keyno: "B2", rooms: ["201", "202"]}] 10 11keys 12 .filter(key => key.rooms.includes("102")) 13 .forEach(it => console.log(it)); 14// {keyno: "A1", rooms: Array(2)}

投稿2020/02/07 03:12

編集2020/02/07 04:54
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/02/07 06:05

配列を扱うテクニックを色々学ばせていただきました。 ありがとうございました。 >room1とかroom2とか誰が決めたんですか? そうなんですよ。他チームがこんなデータしか渡してくれないので、こちらが苦労する事態になっています。 >1番目ルームなのに102号室だったり、 おそらく101は管理人室らしい。。です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問