Biorąc pod uwagę strukturę HTML, która wygląda jak następujący HTML, ale ma arbitralną głębokość. (tj. Może pójść wiele razy głębsze). Ponieważ jest to głębokość arbitray, wolałbym rozwiązanie, które nie wymaga dodania żadnego dodatkowego znacznika do HTML (E.G. Classes)

<ul><!-- Leaf Count 3 -->
  <li>branch 1
    <ul><!-- Leaf Count 2 -->
      <li>leaf 1</li>
      <li>leaf 2</li>
    </ul>
  </li>
  <li>leaf 3</li>
</ul>

Jak mogę liczyć wszystkie liście, które są dzieckiem każdego UL? Więc w tym przykładzie zewnętrzna większość ul miałby 3 liście i zagnieżdżone dwa liście. Wydaje się to jak kwestia rekursji, ale nie mogę przemyśleć.

6
Hopeless 28 czerwiec 2017, 09:30

5 odpowiedzi

Najlepsza odpowiedź

Myślę, że przyjęta odpowiedź nie jest bardziej wydajna. Jest jeszcze prostszy sposób na to.

Możemy użyć jQuery prostej selekcji li:not(:has(*)). Znajdzie to wszystkie elementy LI, które nie ma dzieci (węzeł liści).

Użyj $("#dvMain").find('ul').each, który znajdzie wszystkie elementy ul, a następnie pętla go.

$(document).ready(function() {
    $("#dvMain").find('ul').each(function(item) {
        console.log($(this).find('li:not(:has(*))').length);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="dvMain">
<ul><!-- Leaf Count 4 -->
  <li>branch 1
    <ul><!-- Leaf Count 2 -->
      <li>leaf 1</li>
      <li>leaf 2</li>
    </ul>
  </li>
  <li>branch 1
    <ul><!-- Leaf Count 1 -->
      <li>leaf 1</li>
    </ul>
  </li>
  <li>leaf 3</li>
</ul>
</div>
4
Mayur Patel 28 czerwiec 2017, 07:01

Możesz użyć nawet tego

$('ul').each(function(a){
count = 0;
$(this).find('li').each(function(){
if($(this).children().length ==0){
count++;
}

});
console.log(' ul level '+a+' count : '+count);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul><!-- Leaf Count 3 -->
  <li>branch 1
    <ul><!-- Leaf Count 2 -->
      <li>leaf 1</li>
      <li>leaf 2</li>
    </ul>
  </li>
  <li>leaf 3</li>
</ul>

Demo robocze

0
Amar Singh 28 czerwiec 2017, 07:27

Możesz użyć Treewalker API i suma wszystkich dzieci <ul> To nie ma własnych dzieci.

const treeWalker = document.createTreeWalker(
  document.body,
  NodeFilter.SHOW_ELEMENT
);

const result = [];

while (treeWalker.nextNode()) {
  const node = treeWalker.currentNode;

  if (node.nodeName === 'UL') {
    result.push([...node.querySelectorAll('li')].filter((node) => !node.children.length).length);
  }
};

console.log(result);
<ul>
  <!-- Leaf Count 7 -->
  <li>branch 1
    <ul>
      <!-- Leaf Count 6 -->
      <li>leaf 1</li>
      <li>leaf 2</li>
      <li>branch 2
        <ul>
          <!-- Leaf Count 2 -->
          <li>leaf 1</li>
          <li>leaf 2</li>
        </ul>
      </li>
      <li>branch 3
        <ul>
          <!-- Leaf Count 2 -->
          <li>leaf 1</li>
          <li>leaf 2</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>leaf 3</li>
</ul>
0
Ori Drori 28 czerwiec 2017, 07:01
console.log($("ul.outer>li").length)
console.log($("ul.inner>li").length)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class='outer'><!-- Leaf Count 3 -->
  <li>branch 1
    <ul class="inner"><!-- Leaf Count 2 -->
      <li>leaf 1</li>
      <li>leaf 2</li>
    </ul>
  </li>
  <li>leaf 3</li>
</ul>
  1. Aby policzyć bezpośrednie dziecko używać >
0
guradio 28 czerwiec 2017, 06:35

Jeśli korzystne jest, aby nie zmienić HTML, można użyć jQuery's {x0}}:

function filterLeaf(ele) {
  if ($(ele).children().length === 0) {
    return true;
  }
  return false;
}

var nouter = $('#outer').find('li').filter(function() {
  return filterLeaf(this);
}).length;
var ninner = $('#inner').find('li').filter(function() {
  return filterLeaf(this);
}).length;
console.log(nouter);
console.log(ninner);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul id="outer"><!-- Leaf Count 3 -->
  <li>branch 1
    <ul id="inner"><!-- Leaf Count 2 -->
      <li>leaf 1</li>
      <li>leaf 2</li>
    </ul>
  </li>
  <li>leaf 3</li>
</ul>

Lub, gdy generuje HTML, dodaj nazwę klasową, takie jak "liść" do elementu liściowego, a następnie za pomocą jQuery's .find:

var nouter = $('#outer').find('.leaf').length;
var ninner = $('#inner').find('.leaf').length;
console.log(nouter);
console.log(ninner);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="outer"><!-- Leaf Count 3 -->
  <li>branch 1
    <ul id="inner"><!-- Leaf Count 2 -->
      <li class="leaf">leaf 1</li>
      <li class="leaf">leaf 2</li>
    </ul>
  </li>
  <li class="leaf">leaf 3</li>
</ul>
1
shaochuancs 28 czerwiec 2017, 06:48