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

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

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

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

JavaScript

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

jQuery

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

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

Q&A

解決済

4回答

3082閲覧

javascript(jQuery含む)での文字列のAND検索(絞り込み)

bengal

総合スコア1

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

JavaScript

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

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

jQuery

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

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

0グッド

0クリップ

投稿2020/07/14 05:46

javascript(jQuery含む)を利用して、文字列のAND検索(絞り込み)をしたいと考えています。

ユーザが入力したキーワードで、HTML内に掲載している情報を検索し、一致するものがある場合はその該当情報(リスト)を表示するということがやりたいです。

例えばキーワードが、 「abcd efghij」の場合、
「abcd」と「efghij」両方に該当する情報(リスト)を表示させたいです。

OR検索や、セレクトボックス対応のものは散見されますが、AND検索(絞り込み)は、あまり情報がなかったものですから質問させていただきました。
知識不足ですがご教授よろしくお願いします。

※尚、利用する際の環境はオフライン環境を想定しています。

現状のソースコード

<!doctype html> <html> <head> <meta charset="UTF-8"> <title>TEST</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <!-- <script src="js/jquery-3.5.1.min.js"></script> --> <script> // Key Words Search $(function(){ $('#buttons01').on("click",function(){ var reg = $('#search').val(); var word = reg.toLowerCase(); var words = word.split(" ");
$('#list li').each(function(){ var list = $(this); list.hide(); $('p', this).each(function() { var txt = $(this).html(); var txts = txt.toLowerCase(); for(var i = 0; i < words.length; i++) { if(txts.search(words[i]) != -1) { list.show(); } } }); }); });

});
</script>

</head> <body style="margin:1em;">
<input type="text" id="search"> <input type="submit" value="検索" id="buttons01"> <ul id="list"> <li><p>abcd efghij</p></li> <li><p>uvwxyz hijklm</p></li> <li><p>jklmnop stuvwx</p></li> <li><p>hijklm ghijklmn</p></li> <li><p>opqrst bcdefg</p></li> <li><p>efghij jklmnop</p></li> <li><p>abcd bcdef</p></li> <li><p>cdefg hijklm</p></li> <li><p>bcdef stuvw</p></li> </ul>
</body> </html>

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

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

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

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

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

kei344

2020/07/14 07:02

(質問文は編集できます)質問文のコードはコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
guest

回答4

0

ベストアンサー

こんにちは
こんな感じでいかがでしょうか?

javascript

1$('#buttons01').on('click', function() { 2 const searchKeys = $('#search').val().trim().split(/\s+/); 3 $('li').each(function() { 4 const text = $(this).text(); 5 const matched = searchKeys.every(key => RegExp(`\b${key}\b`, 'i').test(text)); 6 $(this).css('display', matched ? 'list-item' : 'none'); 7 }); 8});

このcodepenのサンプルは、以下のように動作します。

  • たとえば、bcdef を入力して検索をクリックすると、abcd bcdefbcdef stuvw の2つが表示される。
  • 入力したbcdef を消さずに、続けてスペースを打ち、さらに abcd と入力してから検索をクリックすると、bcdefabcdの両方を含む abcd bcdef のみが表示される。
  • 検索ワードに対するマッチングにおいて、大文字と小文字の違いは無視される。
  • 検索ワード入力欄を消去してから検索をクリックすると、すべてのリストアイテムが表示される。

また、正規表現で使っている \b は単語の境界(Word Boundaries)です。

以上、参考になれば幸いです。

追記

コメントから頂きました質問に回答します。

「$('#search').val().trim().split(/\s+/);」部分は、
入力されたキーワードから無駄なスペースを削除したものを取得するという認識で合ってますでしょうか?

はい。おおよそ合ってます。より正確にいうと、

  • 入力された、複数の検索ワードがスペース(やタブなどの空白文字)で区切られた文字列から、検索ワードの配列を取得する

という処理を行っています。具体例を挙げますと、たとえば、#search の input にたとえば以下のように入力されているとします。

abc def xy

すなわち、$('#search').val() が上記のような文字列であるとします。これは、3つの検索ワード abc, def, xy といくつかのスペースを含んでいます。abc の前には1個のスペースがあり、abcdef の間には1個のスペース、defxy との間には2個のスペースがあり、さらにxy の後ろには3個のスペースがあるというものです。これは、検索ワード入力欄で、いくつかのワードを入力したり消したりしているうちに、検索ワードの間のスペースの数が2個以上ある箇所ができてしまったり、先頭の検索ワードの前や最後の検索ワードの後に1個以上スペースが残ってしまっている状況を再現しています。このとき

javascript

1const searchKeys = $('#search').val().trim().split(/\s+/);

によって、searchKeys として以下の配列が取得されます。

["abc", "def", "xy"]

また、「searchKeys.every(key => RegExp(key, 'i').test(text));」部分は、
リスト情報と取得した配列キーワードを検証しているのでしょうか?

はい、そうです。リストアイテム(<li>)に含まれるテキストが、入力された複数の検索ワードに該当しているかを検証しています。より詳しく説明すると、

javascript

1const matched = searchKeys.every(key => RegExp(key, 'i').test(text));

という行によって、左辺の matchedtruefalse のどちらかが入ります。true のときは、ループで回している、各ループ本体における当該の li の内容が複数の検索ワードについてのAND条件に「該当した」ことを表します。逆に false のときは、「該当しなかった」ことを表します。

最後に「matched ? 'list-item'」の部分は
どういった意味を成しているのでしょうか?

その後の : 'none' も含めた

matched ? 'list-item' : 'none'

の部分は、条件(三項)演算子 を使った式です。matched が true のとき 'list-item' 、 false のとき 'none' という文字列を返しますので、

$(this).css('display', matched ? 'list-item' : 'none');

によって、当該li の CSSプロパティdisplay に、matched が true だったら 'list-item'が指定され、falseだったら 'none' が指定されます。各<li>について、CSS display'list-item'が指定されると表示され、'none'が指定されると表示されなくなります。

投稿2020/07/14 06:38

編集2020/07/15 14:34
jun68ykt

総合スコア9058

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

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

bengal

2020/07/14 13:28

jun68yktさま 回答ありがとうございます。 またサンプルコードまで提案いただいきありがとうございます。 早速試してみました。 質問なのですが、codepenサンプルで、「a」や「cd」などの 短いキーワードでも検索できるようにするには どういった記述(正規表現の修正?)になるのでしょうか。 知識乏しく、ご教授いただければ幸いです。
jun68ykt

2020/07/14 15:48

@bengalさん コメントありがとうございます。 > 「a」や「cd」などの短いキーワードでも検索できるようにする というのは、 "a" や "cd" に単語として完全一致しなくても、これらをどこかに含めば検索にヒットさせるようにしたいということと解釈しました。そのようにするためには、回答に挙げたコードで使っている正規表現に含まれる単語境界 \b が不要なので、該当するかどうかの判定フラグ matched を得る行を、以下のように修正すればよいかと思います。 【修正前】 const matched = searchKeys.every(key => RegExp(`\b${key}\b`, 'i').test(text)); 【修正後】 const matched = searchKeys.every(key => RegExp(key, 'i').test(text)); ・動作確認用サンプル(修正版)  https://codepen.io/jun68ykt/pen/ExPegeE?editors=1010 上記の修正版で、再度何かご要望と異なるところがあれば、またコメントからお知らせください。
jun68ykt

2020/07/14 16:12

要点を補足しておきます。 ご質問の本題である、 AND検索(絞り込み)をどのように実現するか? という課題を、私の回答では 配列の every メソッド https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every を使うことで実現しています。 ちなみに、everyと対になるメソッドとして、OR 検索をしたいときに使うメソッドは 配列の some メソッド https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some になります。
bengal

2020/07/15 08:05

返信・回答ありがとうございます。 修正版思い通りの動きで助かります。 さて、改めてお聞きしたいのですが、 「$('#search').val().trim().split(/\s+/);」部分は、 入力されたキーワードから無駄なスペースを削除したものを取得するという認識で合ってますでしょうか? また、「searchKeys.every(key => RegExp(key, 'i').test(text));」部分は、 リスト情報と取得した配列キーワードを検証しているのでしょうか? 最後に「matched ? 'list-item'」の部分は どういった意味を成しているのでしょうか? 矢継ぎ早で申し訳ありませんが、ご教授のほどよろしくお願いします。
jun68ykt

2020/07/15 11:59

@bengalさん 上記のコメントで頂戴した3つのご質問についての返答を、回答のほうに追記しました。参考になれば幸いです。
bengal

2020/07/15 12:21

早速の丁寧な回答ありがとうございます。 おかげさまで理解を深めることができました。 また、質問させていただくかもしれませんが 取り急ぎ、いただいた情報を元に、 作業進めていきたいと思います。 大変助かりました。
jun68ykt

2020/07/15 13:29

どういたしまして。 > おかげさまで理解を深めることができました。 とのことでよかったです????
bengal

2020/07/16 13:11

度々すいません、早速行き詰まってしまい 提案いただいたプログラムで質問があるのですが、 検索後、該当情報がなかった際に 「No matching.」と表示させたく if文に分解して編集したのですが メッセージを表示できません。 matchしなかった場合のメッセージは、 どう編集したら表示できるのでしょうか? $('#buttons01').on('click', function() { const searchKeys = $('#search').val().trim().split(/\s+/); $('li').each(function() { const text = $(this).text(); const matched = searchKeys.every(key => RegExp(key, 'i').test(text)); // $(this).css('display', matched ? 'list-item' : 'none'); if (matched == true) { $(this).css('display', 'list-item'); } else { $(this).css('display', 'none'); $(this).parent().find('div').css('display','block'); } }); }); <input type="text" id="search"><input type="button" value="search" id="buttons01"> <div>No matching.</div> <ul id="list"> <li><p>abcd efghij</p></li> <li><p>uvwxyz hijklm</p></li> <li><p>jklmnop stuvwx</p></li> <li><p>hijklm ghijklmn</p></li> <li><p>opqrst bcdefg</p></li> <li><p>efghij jklmnop</p></li> <li><p>abcd bcdef</p></li> <li><p>cdefg hijklm</p></li> <li><p>bcdef stuvw</p></li> <li><p>vbmio aruvw</p></li> <li><p>erioaf bplkj</p></li> <li><p>abcdefghij</p></li> </ul>
jun68ykt

2020/07/16 20:04

こんにちは > 検索後、該当情報がなかった際に「No matching.」と表示 させるのであれば、No matching.を表示する、または消す、という処理を $('li').each(・・・); の後で行うようにすればよいです。 先のコメントに挙げた、 > ・動作確認用サンプル(修正版) >  https://codepen.io/jun68ykt/pen/ExPegeE?editors=1010 に、No matching.を表示する、または消す、という処理を追加したサンプルが以下です。(追加したコードにはコメント入れてます。) https://codepen.io/jun68ykt/pen/NWxOYLL?editors=1010 参考になれば幸いです。
bengal

2020/07/17 08:37

1日中、色々と試していましたが、全然思いつかないやり方でした。 知識不足を痛感しております。ありがとうございました。
guest

0

こんな感じでどうでしょうか?

投稿2020/07/14 06:37

yambejp

総合スコア114574

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

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

yambejp

2020/07/14 06:37

<script> $(function(){ $('#buttons01').on('click',function(){ var keywords=$('#search').val().trim().split(/ +/); $('#list li').show().filter(function(){ var v=$(this).text(); return keywords.reduce((x,y)=>(x+=new RegExp(y).test(v)?0:1,x),0); }).hide(); }); }); </script> <input type="text" id="search" value="abcd efghij"> <input type="button" value="検索" id="buttons01"> <ul id="list"> <li><p>abcd efghij</p></li> <li><p>uvwxyz hijklm</p></li> <li><p>jklmnop stuvwx</p></li> <li><p>hijklm ghijklmn</p></li> <li><p>opqrst bcdefg</p></li> <li><p>efghij jklmnop</p></li> <li><p>test abcd test efghij test</p></li> <li><p>abcd bcdef</p></li> <li><p>cdefg hijklm</p></li> <li><p>bcdef stuvw</p></li> </ul>
yambejp

2020/07/14 06:41

「abc」というテキストに「a」というキーワードはヒットするのかどうかですね。 あとは正規表現のワイルドカードをエスケープするかどうかとか いくつかポイントがあります
bengal

2020/07/14 13:26

yambejpさま 回答ありがとうございます。 提案いただいたサンプルでは 「a」「bc」などでも検索でき完璧だと思うのですが、 「「a」というキーワードはヒットするのかどうか」、 「正規表現のワイルドカードをエスケープするかどうか」といった回答の意味は プログラムに何か問題があることを暗示しているのでしょうか? 自身の初心者レベルでは問題無いように見えるのですが・・。 メールアドレス程度の正規表現知識しかないので 教えていただければ幸いです。
yambejp

2020/07/14 14:43

たとえば正規表現のキーワードをパターンだとすると 「.」とかで検索するとすべてがヒットしたり 「[abc]」で検索するとaかbかcにヒットしたりします。 これらの文字にズバリヒットさせるには 「.」や「[abc]」などエスケープ処理が必要になります
bengal

2020/07/15 07:37

返信ありがとうございます。 検索目的に合わせて、正規表現パターンの生成が必要ということですね。 追記で質問なのですが、 「reduce()」は、各要素を順に繋ぎ合わせたものと思われますが、 「return keywords.reduce((x,y)=>(x+=new RegExp(y).test(v)?0:1,x),0);」部分で 検索キーワード「keywords.」と検索される側の情報「v」とで どういった流れで検証作業が行われているのでしょうか? また、「(x+=new RegExp(y).test(v)?0:1,x),0);」の正規表現は どういった意味になるのでしょうか? 色々調べたのですが???でしたので・・。
yambejp

2020/07/15 08:58

一つ一つのキーワードをyで受け、マッチしたら0、しなかったら1をxに足します。 つまり一つでもマッチしないキーワードがあれば1以上の数字=trueになり それをfillterで利用して「マッチしないものがあればhideしている」わけです
yambejp

2020/07/15 09:12

すこし丁寧に書くとこんな感じ $(function(){ $('#buttons01').on('click',function(){ var keywords=$('#search').val().trim().split(/ +/); $('#list li').show().filter(function(){ var v=$(this).text(); var num=keywords.reduce(function(x,y){ if(!new RegExp(y).test(v)){ x++; } return x; },0); return num==0?false:true; }).hide(); }); });
bengal

2020/07/15 12:45

丁寧に書いていただき恐縮ですが、 「1以上の数字=true」というのは、「0?false:true」部分を表すのでしょうか?
guest

0

splitで回したキーワードwordsをすべてを含んでいるかどうか判断すればいいと思います。
or検索はどれか一つ、and検索はすべて。

投稿2020/07/14 06:39

sousuke

総合スコア3828

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

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

bengal

2020/07/14 13:28 編集

sousukeさま 回答ありがとうございます。 流れは何となくわかるのですが and検索の「判断」部分が何とも停滞しておりまして・・。
guest

0

ダミーのコードのため、正規表現はお望みのものにならないと思うので、流れだけ。
該当する内容によって表示する内容が変わるのであれば処理も分けた方がいいかもしれませんね

var arr = ["Red", "Green", "Blue"]; //ここに正規表現を入れる var searchWord = "検索対象文字" arr.forEach(function( value ) { if (searchWord.match(value)){ //文字列が含まれなければnullが返ることを利用して判定 displayList(value) } }); function displayList(value){ if(value == "a"){ // a用のリストを表示する処理 }elseif(value == "b"){ // b用のリストを表示する処理 } //以下同様で合致するリストを表示 }

投稿2020/07/14 06:18

mikan_s4n

総合スコア377

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

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

bengal

2020/07/14 13:24

mikan_s4nさま 回答ありがとうございます。 該当部分コード、分解・解読して試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問