为什么这个随机播放功能只适用于 4+ 项目?包含 JsFiddle

Why does this shuffle function only work with 4+ items? JsFiddle included

我有以下代码,它随机播放 table 行中的一组项目。但是,shuffle 功能只有在有 4+ 项时才有效:

var parent = $("#parent");


function shuffleRows(parent) {
  var rows = parent.children().children(".shuffledtd1");
  for (var i = rows.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = rows[i];
    rows.eq(i - 1).after(rows[j]);
    rows.eq(j - 1).after(temp);
  }
}

shuffleRows(parent);
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<table>
  <tbody id="parent">

    <tr id="node2" class="shufflerow">
      <td class="shuffledtd shuffledtd1">AA</td>
      <td class="shuffledtd shuffledtd1">BB</td>

      <!-- IF I DELETE THIS AND THE FOLLOWING ROW, THE PRIOR 2 ROWS NO LONGER SHUFFLE -->
      <td class="shuffledtd shuffledtd1">CC</td>
      <td class="shuffledtd shuffledtd1">DD</td>
    </tr>

  </tbody>
</table>

完整代码:http://jsfiddle.net/d8rkgx0z/

我认为这与这部分代码有关:

    rows.eq(i - 1).after(rows[j]);
    rows.eq(j - 1).after(temp);

但是,不幸的是,我的技能不够强大,无法在没有数小时的反复试验的情况下隔离和纠正问题。

在此先感谢您的帮助!

不用调用children两次,直接传入单元格的parent即可。此外,使用 jQuery#sort:

洗牌 children 更容易
var parent = $("#node2");                                        // parent should be the tr element not the tbody which is in fact a grandparent not a parent

function shuffleChildren(parent) {
  parent.children()                                              // get the children of the parent element
        .sort(function() { return Math.random() - 0.5; })        // sort them randomly (shuffling)
        .appendTo(parent);                                       // add them back to parent so that the shuffling takes effect
}

shuffleChildren(parent);

示例:

var parent = $("#node2");                                        // parent should be the tr element not the tbody which is in fact a grandparent not a parent

function shuffleChildren(parent) {
  parent.children()                                              // get the children of the parent element
        .sort(function() { return Math.random() - 0.5; })        // sort them randomly (shuffling)
        .appendTo(parent);                                       // add them back to parent so that the shuffling takes effect
}

shuffleChildren(parent);
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<table>
  <tbody id="parent">
    <tr id="node2" class="shufflerow">
      <td class="shuffledtd shuffledtd1">AA</td>
      <td class="shuffledtd shuffledtd1">BB</td>
      <td class="shuffledtd shuffledtd1">CC</td>
      <td class="shuffledtd shuffledtd1">DD</td>
    </tr>
  </tbody>
</table>

注意:如果要对所有行执行此操作,则只需使用jQuery#each:

$("#parent tr").each(function() {                                // get all tr inside #parent
    shuffleChildren($(this));                                    // shuffle their children
});

顺便说一句,您要洗牌的是单元格而不是行。

您的脚本可以大大简化,尤其是使用适当的选择器和随机排序器(涵盖了在 tr 中排序 tdtr 中的两种情况 tbody:

const randomSorter = () => 0.5 - Math.random();

$('.shufflecells tr').each(function() {
  $(this).html($('td', this).sort(randomSorter));
});

$('.shufflerows').each(function() {
  $(this).html($('tr', this).sort(randomSorter));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<table>
  <tbody class="shufflecells">
    <tr>
      <td>AA</td>
      <td>BB</td>
      <td>CC</td>
      <td>DD</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody class="shufflecells">
    <tr>
      <td>AA</td>
      <td>BB</td>
    </tr>
  </tbody>
</table>

<table>
  <tbody class="shufflerows">
    <tr>
      <td>AA</td>
    </tr>
    <tr>
      <td>BB</td>
    </tr>
    <tr>
      <td>CC</td>
    </tr>
    <tr>
      <td>DD</td>
    </tr>
  </tbody>
</table>

ibrahim mahrir 的回答是做你想做的事情的更优雅的方式,但为了帮助你理解为什么你的解决方案不起作用,我也发布了这个。

问题:

您看到的问题是因为当 i = 0 时,当您执行 (i - 1) 时得到负数,这在您的 table.

中不是有效索引

rows.eq(i - 1).after(rows[j]);

使您的解决方案有效的方法:

以下是您可以如何使用现有代码解决该问题:

function shuffleRows(parent) {
    var rows = parent.children().children(".shuffledtd1");
    // Changed to i >= 0.
    for (var i = rows.length - 1; i >= 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = rows[i];
        // Changed to just i, instead if i-1.
        rows.eq(i).after(rows[j]);
        rows.eq(j - 1).after(temp);
    }
}

$('button').on('click', function() {
 shuffleRows($("#parent"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
    <tbody id="parent">

        <tr id="node2" class="shufflerow">
            <td class="shuffledtd shuffledtd1">AA</td>
            <td class="shuffledtd shuffledtd1">BB</td>
            <td class="shuffledtd shuffledtd1">CC</td>

        </tr>
  
    </tbody>
</table>
<button>Shuffle</button>

这个代码片段只是做了两个小改动,我在代码中做了标记,以避免您遇到的负索引问题。

同样,有很多更优雅的方法来完成这项任务,但我总是搞不懂为什么有些东西不起作用,所以我希望你能得到一个解释。