【问题标题】:Jquery Sort by element value in arrayJquery 按数组中的元素值排序
【发布时间】:2016-06-19 12:51:51
【问题描述】:

我有这个 dom:

<ul id="appsList">
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>ios</span></li>
    <li><span>some value</span> <span>facebook</span></li>
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>ios</span></li>
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>android</span></li>
</ul>

我想按我得到的数组对列表项进行排序:

数组可以是:[ios,android,facebook] 和它的任何其他组合,不一定包含所有键,可以只是[ios]

我希望列表按数组排序,所以如果我在其中有[ios,android,facebook],那么列表将像这样排序:

<ul id="appsList">
    <li><span>some value</span> <span>ios</span></li>
    <li><span>some value</span> <span>ios</span></li>
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>android</span></li>
    <li><span>some value</span> <span>facebook</span></li>
</ul>

【问题讨论】:

标签: javascript jquery arrays sorting


【解决方案1】:

更新

Final Plunker

例如:

<li><span>some value</span> <span class="sort">android</span></li>

并使用.find("sort")


您必须调整 .sort() 函数,

var arr = ['ios','android','facebook'] ;

var $li = $('#appsList li').sort(function(a,b) {
      var firstValue = $(a).find('.sort').text();
        var secondValue = $(b).find('.sort').text();

        var first = arr.indexOf(firstValue);
        var second = arr.indexOf(secondValue);

        var output = (second === -1 && first > -1) ? -1 :
        (second > -1 && first === -1) ? 1 :
        (second === -1 && first === -1) ? firstValue > secondValue :
        (second > first ? 1 : -1);
        return output;
});

$('#appsList').html($li);

示例 sn-p。

var arr = ['ios','android','facebook'] ;
    
var $li = $('#appsList li').clone().sort(function(a,b) {

        var firstValue = $(a).find('.sort').text();
        var secondValue = $(b).find('.sort').text();

        var first = arr.indexOf(firstValue);
        var second = arr.indexOf(secondValue);

        var output = (second === -1 && first > -1) ? -1 :
        (second > -1 && first === -1) ? 1 :
        (second === -1 && first === -1) ? firstValue > secondValue :
        (second > first ? 1 : -1);
        return output;
});

$('#resultAppsList').html($li)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Before sort : 
 <ul id="appsList">
    <li><span>some value</span> <span class="sort">android</span></li>
    <li><span>some value</span> <span class="sort">ios</span></li>
    <li><span>some value</span> <span class="sort">facebook</span></li>
    <li><span>some value</span> <span class="sort">android</span></li>
    <li><span>some value</span> <span class="sort">ios</span></li>
    <li><span>some value</span> <span class="sort">android</span></li>
    <li><span>some value</span> <span class="sort">android</span></li>
 </ul>

After sort :
<ul id="resultAppsList">
</ul>

【讨论】:

  • 值得注意的是,在这种情况下,$(this).text() 将与$(this).find('span').text() 完全相同,因此可以将链减少一点以避免不必要的工作;此外,如果您缓存要使用的文本属性 (var textProp = 'textContent' in document? 'textContent' : 'innerText'),那么您可以轻松地在该部分中避免使用 jQuery,而只需使用 this[textProp] 来检索文本。但是对于那些微小的变化,做完全相同的事情真的不值得单独回答。
  • 我正在经历一个非常困难的答案,然后我使用sort() 完美地看到了你的答案,这让我大吃一惊!干得好
  • @DavidThomas,是的,你完全正确。我已将该行添加到我的答案中。我没有使用$(this).text()的原因是li可能包含一些文本,结果纯粹基于spans的内容。你的第二点也是有效的。
  • 是的,这在很大程度上是个案的可能性,如果您在没有警告困难的情况下采用这种方法,我想您无论如何都会让 cmets 指出这个问题。有些日子你就是赢不了! ;-)
  • 已更新 Plnkr 呃。我犯的愚蠢错误!
【解决方案2】:

虽然这在 jQuery 中当然是完全可能的,但值得注意的是 jQuery 不能做原生 DOM 不能做的事情。因此,为了补充其他答案,我选择使用 ES5 提供非 jQuery 方法,以保持与旧浏览器的兼容性(尽管稍后提供 ES6 替代方案):

// caching the '#appsList' element:
var list = document.getElementById('appsList'),

  // working out which text-property is present in the browser
  // (Chrome and Firefox, to the best of my knowledge, support
  // both innerText and textContent; whereas IE < 9 supports
  // only innerText):
  textProp = 'textContent' in document ? 'textContent' : 'innerText',

  // retrieving an Array of the (element) children of the list,
  // using Array.prototype.slice() and Function.prototype.call()
  // to turn the collection of child elements into an Array;
  // we then sort the Array using Array.prototype.sort() and
  // its anonymous function:
  sorted = Array.prototype.slice.call(list.children, 0).sort(function(a, b) {
    // here we find the first/only <span> element in the previous
    // Array element ('a') and the first/only <span> in the current
    // ('b') element and comparing its text:
    return a.querySelector('span')[textProp] > b.querySelector('span')[textProp];
  }),

  // creating a documentFragment:
  fragment = document.createDocumentFragment();

// iterating over the sorted Array of elements:    
sorted.forEach(function(el) {

  // appending a clone of the element ('el') to the
  // fragment (in order to show the before/after together):
  fragment.appendChild(el.cloneNode(true));
});

// retrieving the element to show the newly-sorted result:
document.getElementById('resultAppsList').appendChild(fragment);

var list = document.getElementById('appsList'),
  textProp = 'textContent' in document ? 'textContent' : 'innerText',
  sorted = Array.prototype.slice.call(list.children, 0).sort(function(a, b) {
    return a.querySelector('span')[textProp] > b.querySelector('span')[textProp];
  }),
  fragment = document.createDocumentFragment();

sorted.forEach(function(el) {
  fragment.appendChild(el.cloneNode(true));
});
document.getElementById('resultAppsList').appendChild(fragment);
ul {
  list-style-type: none;
  margin: 0 0 1em 0;
  padding: 0;
  display: inline-block;
  width: 45vw;
  box-sizing: border-box;
}
li {
  width: 100%;
  padding: 0;
  margin: 0 0 0.2em 0;
}
span {
  margin-left: 1em;
}
ul::before {
  content: attr(data-state)': ';
  margin-bottom: 0.2em;
  display: block;
  width: 60%;
  border-bottom: 1px solid #000;
  color: limegreen;
}
<ul id="appsList" data-state="Before">
  <li>1<span>android</span>
  </li>
  <li>2<span>ios</span>
  </li>
  <li>3<span>facebook</span>
  </li>
  <li>4<span>android</span>
  </li>
  <li>5<span>ios</span>
  </li>
  <li>6<span>android</span>
  </li>
  <li>7<span>android</span>
  </li>
</ul>
<ul id="resultAppsList" data-state="After">
</ul>

JS Fiddle demo.

为了让上述内容更适合现代浏览器,我们在此处进行了 ES6 更新(尽管我怀疑它可能甚至更多 ES6-ified):

// using the let statement to initialise variables:
let list = document.getElementById('appsList'),
  textProp = 'textContent' in document ? 'textContent' : 'innerText',

  // using Array.from() to convert the Array-like collection into an
  // Array:
  sorted = Array.from(list.children).sort(function(a, b) {
    return a.querySelector('span')[textProp] > b.querySelector('span')[textProp];
  }),
  fragment = document.createDocumentFragment();

// using Arrow functions within the Array.prototype.forEach() call, since we're
// not using the 'this' keyword and it's pleasantly abbreviated:
sorted.forEach(el => fragment.appendChild(el.cloneNode(true)));

document.getElementById('resultAppsList').appendChild(fragment);

let list = document.getElementById('appsList'),
  textProp = 'textContent' in document ? 'textContent' : 'innerText',
  sorted = Array.from(list.children).sort(function(a, b) {
    return a.querySelector('span')[textProp] > b.querySelector('span')[textProp];
  }),
  fragment = document.createDocumentFragment();

sorted.forEach(el => fragment.appendChild(el.cloneNode(true)));
document.getElementById('resultAppsList').appendChild(fragment);
ul {
  list-style-type: none;
  margin: 0 0 1em 0;
  padding: 0;
  display: inline-block;
  width: 45vw;
  box-sizing: border-box;
}
li {
  width: 100%;
  padding: 0;
  margin: 0 0 0.2em 0;
}
span {
  margin-left: 1em;
}
ul::before {
  content: attr(data-state)': ';
  margin-bottom: 0.2em;
  display: block;
  width: 60%;
  border-bottom: 1px solid #000;
  color: limegreen;
}
<ul id="appsList" data-state="Before">
  <li>1<span>android</span>
  </li>
  <li>2<span>ios</span>
  </li>
  <li>3<span>facebook</span>
  </li>
  <li>4<span>android</span>
  </li>
  <li>5<span>ios</span>
  </li>
  <li>6<span>android</span>
  </li>
  <li>7<span>android</span>
  </li>
</ul>
<ul id="resultAppsList" data-state="After">
</ul>

参考资料:

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多