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

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

ただいまの
回答率

90.84%

  • JavaScript

    14799questions

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

  • jQuery

    6154questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Lodash

    11questions

    Lodashは、JavaScriptのユーティリティライブラリ。Underscoreの派生ライブラリで、配列・オブジェクトの操作に便利です。また、コードの可読性も高めることができます。

jQueryで配列の語句を前方一致させたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 150

toramo

score 5

 実現したいこと

こんにちは。恐らく初歩中の初歩のような質問になりますがよろしくお願いいたします。
配列に記入した語句をもとにhtmlの内容を絞り込みたいのですが、
前方一致させたいものが部分一致のものと混ざってしまい困っています。

javascriptやhtmlの元データは前回同様こちらを参考にしています。
また、lodash.jsが必要になります。

 発生している問題

var Lists= [
 { name: 'あいうえお', hobby: [['趣味1', '30', 'あいうえお'], ['趣味2', '20', 'いうええ'], ['趣味3', '40', 'うえお']]},
 { name: 'かきくけこ', hobby: [['趣味1', '50', 'かいう'], ['趣味2', '30', 'うえこあいうえお'], ['趣味3', '40', 'くあい'], ['趣味4', '40', 'けえこ']]}
 { name: 'さしすせそ', hobby: [['趣味1', '20', 'いうさ'], ['趣味2', '40', 'しかい']]}
];


のような配列がある時にhtml側のドロップダウンリストを使って絞り込みをしたいのですが、今までは

function filterBydesc(value) {
    return (value == "") ? _.constant(true) : function(item) {
       var ranges = {
                1: {desc: "いう"},
                2: {desc: "うえ"},
                3: {desc: "かい"},
           };
        var range = ranges[value];
          return _.some(range, function(descword) {
            return _.some(item.desc, function(word) {
                 return _.includes(word, descword);
                        });
                  });
                };
    }


のように記述することで、その語句を含む人物を取り出すことができました。
しかし、絞り込みの条件を考える中でどうしても「あいうえお」で始まる人のみ絞り込みたくなったのですが
そのままだと「うえこあいうえお」を持つかきくけこさんも結果に表示されてしまいます。

 試したこと

前方一致の正規表現というものを知ったので

                4: {desc: ^"あいうえお"},
                4: {desc: "^あいうえお"},
                4: {desc: \^あいうえお\},


上記の式にこの3パターンをそれぞれ付け足して試してみましたが
一番上はエラーとなり表示されず、二番目と三番目は「当てはまる人物は0名です」となりました。
そこで

function filterBydesc2(value) {
    return (value == "") ? _.constant(true) : function(item) {
       var ranges = {
                1: {desc: "あいうえお"},
        };
        var range = ranges[value];
            return _.some(range, function(descword) {
            return _.some(item.desc, function(word) {
                    if (word.indexOf(descword) === 0){
                     return _.includes(word, descword);
                            };
                      }); 
                });
             };
    }


と別個に関数を作成したところ、きちんとあいうえおさんのみ表示してくれました。
しかし1つのドロップダウンを変更した時にどちらの絞り込みもしたいので、
どうにか上の関数にこの表現を入れ込めないかと最初の「filterBydesc」の関数内に
カッコを入れ替えたりしてペーストしてみたのですが思うように動きません。

最初の関数内に前方一致の条件も付け加えることは可能でしょうか。
教えていただきたく思います。よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

Answer書き直しました。

const _ = require('lodash')

function filterBydesc (value) {
  return value == ''
    ? _.constant(true)
    : function (item) {
      var ranges = {
        1: { desc: 'いう' },
        2: { desc: 'うえ' },
        3: { desc: 'かい' },
        4: { desc: '^あい' } // <---- 条件追加しました。
      }
      var range = ranges[value]
      return _.some(range, function (descword) {
        return _.some(item.desc, function (word) {
          return !!word.match(descword) // <---- ここを書き換えました。
        })
      })
    }
}

/* 動作確認用 */
console.log(filterBydesc('1')({ desc: { word: 'あいうえお' } })) // true
console.log(filterBydesc('2')({ desc: { word: 'あいうえお' } })) // true
console.log(filterBydesc('3')({ desc: { word: 'あいうえお' } })) // false

/* 本題 */
console.log(filterBydesc('4')({ desc: { word: 'あいうえお' } }))    // true
console.log(filterBydesc('4')({ desc: { word: '___あいうえお' } })) // false

_.includes('foobar', 'foo')は単に true か false を返すので、このケースでは lodash にこだわる必要なさそうでした。
'foobar'.match('^foo')とすると正規表現込みのマッチングが行われるので、これを使うと良いと思います。

'foobar'.match('^foo')     // [ 'foo', index: 0, input: 'foobar' ]
'___foobar'.match('^foo')  // null

このままだと返す値が若干怪しいので、!!を適用して true か false にしてから返すと良いと思いました。

!!'foobar'.match('^foo')     // true
!!'___foobar'.match('^foo')  // false

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/11 23:27

    回答ありがとうございます。
    こちらの式に変更しても、正しく動作することができました。
    しかし、この条件に加えて
    「1: {desc: "いう"},
    2: {desc: "うえ"},
    3: {desc: "かい"},」
    などの部分一致の条件を同時に成立させたいのです。
    説明不足で申し訳ありません。

    キャンセル

  • 2018/05/12 05:09

    「nameで前方一致し、かつdescで部分一致させるレコードを探す」ということでしょうか?

    キャンセル

  • 2018/05/12 23:45

    何度も有難うございます。こちらの表現不足でお手を煩わせてしまいすみません。
    1〜4のdescが同じ変数内に配列として並んでいるときに、
    1・2・3のdescは部分一致させ、4の「あいうえお」というdescのみ前方一致させたい、という意味で質問させていただきました。
    なんとなく、同じ変数内では出来ないのでは?と考え
    123と4の配列をそれぞれ別の変数として定義して、
    上の方に教えていただいたstartsWithを絡めたif文を作ればいいのではないかと思ったのですが
    (全くの素人考えのためズレていたらすみません)
    その構文が正しく書けないため手詰まっています。

    キャンセル

  • 2018/05/12 23:51

    把握しました!Answer修正しようと思います。

    キャンセル

  • 2018/05/13 13:54

    有難うございました!
    修正していただいた回答のお陰で、無事に前方一致させることが出来ました!
    ドロップダウンを変更して正しい人数に絞り込めたのを見た時に本当にホッとしました。
    教えていただいた表現を自分で調べながら学んでみようと思います。
    今回は大変お世話になりました。

    キャンセル

  • 2018/05/13 13:55

    おめでとうございます!

    キャンセル

+1

最初の関数内に文頭一致の条件も付け加えることは可能でしょうか。

startsWith
https://lodash.com/docs/4.17.4#startsWith

「文頭一致」は前方一致が正しいですね。

Re: toramo さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/11 23:36 編集

    回答ありがとうございます。
    前方一致ですね。不勉強で申し訳ないです。本文を修正しました。

    startsWithの項目を読みました。
    恐らく、前方一致させたい配列をもう一つvar ranges2などにして表記した上で
    if文で0文字目からstartsWithしてたらranges2の方の式、elseでrangeの式とすれば
    一つの関数内で収まるんだろうな、というぼんやりとした道筋は分かりました。
    ただ、申し訳ないのですがその関数を正しく表記できる力がまだ無かったため、
    今回は別の方の関数をそのまま使わせていただきました。
    しかし今後似たような場面に遭遇した際にこのstartsWithも使いこなせるように精進します。
    お手数おかけしました。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    14799questions

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

  • jQuery

    6154questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Lodash

    11questions

    Lodashは、JavaScriptのユーティリティライブラリ。Underscoreの派生ライブラリで、配列・オブジェクトの操作に便利です。また、コードの可読性も高めることができます。