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

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

ただいまの
回答率

89.08%

jQueryで配列から一致する数をカウントする

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,256

skipping

score 14

目的

子リストの数をカウントしたいです。

問題のコード

コードが長くてすみません。まずはサンプルです。
https://jsfiddle.net/psn5849w/136/

上のサンプルは下記コードですが、問題はjQueryの
var my_child_count = (parents.indexOf(my_post_num)).length;//カウントされない?
という部分でカウントされないことです。

これは配列parentsからmy_post_numと一致する数をlengthでカウントしているつもりですが、なぜかundifindになってしまいます。

改めまして目的ですが、このカウントを使って最後の行の
$(this).find('.count-box').text(my_child_count); 
.count-boxのテキストをカウント数に書き換えることです。

なぜカウントされないのか、ご教示頂ければと思いご質問させて頂きました。

<div class="alllists">
  <ul>

    <li>
      <div id="post-7" class="list" parent="0" ancestor="">A
            <span class="my_post_num"></span><span class="my_ancestor_num"></span>
      </div>
    </li>

    <li>
      <div id="post-157" class="list" parent="0" ancestor="">B
        <span class="my_post_num"></span><span class="my_ancestor_num"></span>
      </div>
      <ul class="childrens">
        <li>
          <div id="post-200" class="list" parent="157" ancestor="">C(Bの子)
            <span class="my_post_num"></span><span class="my_ancestor_num"></span>
          </div>
        </li>      
        <li>
          <div id="post-354" class="list" parent="157" ancestor="">D(Bの子)
            <span class="my_post_num"></span><span class="my_ancestor_num"></span>
          </div>
        </li>
        <li>
          <div id="post-365" class="list" parent="354" ancestor="">E(Dの子)
            <span class="my_post_num"></span><span class="my_ancestor_num"></span>
          </div>
        </li>         
      </ul>
    </li>

  </ul>
</div>
//先祖番号の連結
function getParentNums(list) {
  var parent_num = list.attr('parent');
  if (parent_num == "0") {
  return ["0"];
  }
  var parent = $("#post-" + parent_num); 
  var parent_nums = getParentNums(parent);
  parent_nums.push(parent_num);
  return parent_nums;
}
$('.list').each(function() {
  var my_post_num = $(this).attr('id').split('-')[1]; 
  var list = $(this);
  var parents = getParentNums(list);
  var my_ancestor_num = parents.join('-');
  list.attr('ancestor',my_ancestor_num);
  //確認のための表示
  $(this).find('.my_post_num').text(my_post_num);
  $(this).find('.my_ancestor_num').text(my_ancestor_num);
});

//子がいたら「ボタン」表示し、「子の数」を書き換える
var parents = [];
$(".list").each(function() {
  var parent_num = $(this).attr('parent'); 
  parents.push( parent_num );
});
$(".list").each(function() {
  $(this).after('<p>子の数:<span class="count-box">0</span></p>');
  var my_post_num = $(this).attr('id').split('-')[1];
  var my_child_count = (parents.indexOf(my_post_num)).length;//カウントされない?
  if (parents.indexOf(my_post_num) >= 0){
    $(this).append('<button>ボタン</button>');
    $(this).find('.count-box').text(my_child_count);    
  }
});


夜分に長いコードを提示して大変恐縮ではございますが、どうぞ宜しくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

これは配列parentsからmy_post_numと一致する数をlengthでカウントしているつもりですが、なぜかundifindになってしまいます。

indexOf の理解が誤っているのでは。
indexOfの戻り値は、例えばconst array = [5, 3, 6, 7, 1, 6, 1]のような配列があったとき、
array.indexOf(1)の戻り値は4です。
array.indexOf(2)の戻り値は-1です。

そしてlengthStringまたはArrayのプロパティです。
Numberlengthプロパティはありません。

var my_child_count = (parents.indexOf(my_post_num)).length;
ここでやりたいのはおそらく
var my_child_count = parents.filter(num => num === my_post_num + '').length;
こういうことですよね。

これはparentsという配列からmy_post_numに一致する要素のみ抽出して新しい配列を作り、その長さを取得しています。
parents配列には文字列で数字が入っていたので、my_post_numは文字列に変換して比較しています。
厳密な比較が必要ないなら=== my_post_num + ''のところを=2個にして、== my_post_numにしても良いです。

で、直後のif文も条件式が誤っているので修正すればやりたいことができると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/04 08:24 編集

    おはようございます。とても丁寧にご説明頂き誠にありがとうございます。

    ご指摘の2点(と、あとcount-box挿入位置)を修正したところ、無事に目的のカウントができました。



    indexOfは該当位置を返すのですね。ありがとうございます。次のように誤解しておりました。

    すなわち、
    『var my_child_count = (parents.indexOf(my_post_num)).length;』
    の部分は、
    『var my_child_count =(parents の中から、my_post_num に該当するもの)。それを数える』
    という指示のつもりでおりました。

    なるほど。そうではなく該当位置を返すのなら、たしかにlengthで数えるわけにはいきませんね。理解致しました。ご指導に深く感謝です。



    それにしても、
    『var my_child_count = parents.filter(num => num === my_post_num + '').length;』
    これは難しいですね。

    『var my_child_count = parents にフィルターをかける(✕✕という内容で)。それを数える』
    しか分かりません。

    『num => num』は一体どんな指示になるの?『+』の意味は何なのか?疑問が絶えず…、

    もしお時間がございましたらご教示頂けましたら幸いです。
    (ご面倒でしたらスルーしてくださって結構です。どうもありがとうございました。)

    キャンセル

  • 2018/09/04 09:52 編集

    横から失礼いたします。
    私もPHPやJavaScript(jQuery)を学習中の身です故、知識確認も含め、可能な範囲でお手伝いさせていただきたく。

    先ずは「filter」について、こちらをご確認いただけますと理解が深まるかと思います。
    Array.prototype.filter() - JavaScript | MDN - Mozilla
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

    ×『num => num』の表記は『key => value』の関係です。
    ×この説明で疑問符が浮かぶようであれば、配列についての基礎知識の学習をお勧めいたします。
    ⇒申し訳ないです。お恥ずかしながら誤認識でした…。

    『+』は変数「my_post_num」と後続の文字列「」(''の中)を連結するためのもの…なのですが、
    この比較において「my_post_num」にくっつける意図は私では理解しきれませんでした…。
    ⇒回答者様の説明にある通り、「my_post_num」を文字列型に変換するために付与しているのですね。
    数値に文字列を連結すると型が変換される(数値型⇒文字列型)ようです。
    (変数と文字列の連結自体は基礎知識であるので、こちらも調べてみるとよろしいかと)

    ご理解の一助になれば幸いです。
    #誤認識等ありましたらご指摘いただきたく存じます。

    キャンセル

  • 2018/09/04 10:18

    num => num === my_post_num + ''
    この記述は「アロー関数」と言います。
    (num) => {
    return num === my_post_num + '';
    }
    このような記述を省略したものです。
    numを引数にとり、numと文字列に変換したmy_post_numが一致する場合にtrueを返す関数です。
    Array.prototype.filter()の引数は関数で、trueを返した要素だけを名前の通りフィルターします。
    「アロー関数」がどういうものかはこちらを参照してください。
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions

    キャンセル

  • 2018/09/05 22:48

    spookybird様、ご返信遅くなりまして大変申し訳ございません。記述の省略はいろいろ経験しないと難しそうですね。アロー関数についてはリンク先を参照し少しだけわかりました。どうもありがとうございました。

    madoka9393様もご考察をありがとうございます。お蔭さまで「filter」について理解理解できました。

    キャンセル

0

できたものです。
https://jsfiddle.net/psn5849w/146/

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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