【问题标题】:Custom sort of dropdown options using jQuery使用 jQuery 的自定义下拉选项
【发布时间】:2020-08-11 02:41:12
【问题描述】:

我在对下拉菜单的选项进行排序方面需要帮助。我有以下内容:

<select name="models" id="models">
    <option value="14b">14b</option>
    <option value="ab">ab</option>
    <option value="14">14</option>
    <option value="bc">bc</option>
    <option value="15">15</option>
    <option value="101">101</option>
    <option value="13">13</option>
</select>

我想对选项进行排序,使其如下所示:

<select name="models" id="models">
    <option value="ab">ab</option>
    <option value="bc">bc</option>
    <option value="13">13</option>
    <option value="14">14</option>
    <option value="14b">14b</option>
    <option value="15">15</option>
    <option value="101">101</option>
</select>

下拉菜单有两种类型的条目,一种以数字开头,另一种以字母开头。我想首先简单地按字母顺序对以字母开头的那些进行排序,并将它们放在下拉列表的开头。然后,一些以数字开头的字母偶尔会在末尾有一两个字母。有字母的会被认为比没有字母的要大一步,然后会被定位,因此顺序例如是 14 > 14b > 15

我搜索并找到了几篇关于如何对列表/下拉列表进行排序的帖子,但这有点复杂,我似乎无法自己弄清楚如何将所有内容拼凑在一起。有人可以帮忙吗? 谢谢!

【问题讨论】:

    标签: javascript jquery arrays sorting


    【解决方案1】:

    试试这个

    function natcmp(a, b) {
        var ra = a.innerText.match(/\D+|\d+/g);
        var rb = b.innerText.match(/\D+|\d+/g);
        var r = 0;
    
        while(!r && ra.length && rb.length) {
            var x = ra.shift(), y = rb.shift(),
                nx = parseInt(x), ny = parseInt(y);
            if(isNaN(nx) && isNaN(ny))
               { r = x > y ? 1 : -1}
            else if(isNaN(nx) || isNaN(ny))
               { r = x < y ? 1 : (x > y ? -1 : 0); }
            else
                r = nx - ny;
        }
        return r || ra.length - rb.length;
    }
    
    
    $("#models").html(
    Array.prototype.slice.call($("#models")[0].querySelectorAll("option"), 0).sort(natcmp)
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <select name="models" id="models">
        <option value="14b">14b</option>
        <option value="ab">ab</option>
        <option value="14">14</option>
        <option value="bc">bc</option>
        <option value="15">15</option>
        <option value="101">101</option>
        <option value="13">13</option>
    </select>

    【讨论】:

    • 感谢您花时间回答我的问题!这很好用,几乎即插即用。我选择另一个帖子作为“答案”,因为它是第一个并且它有 cmets,但我觉得这可能是一种更优雅的方法,因为我作为一个新手更难理解。无论如何,我感谢您抽出时间提供帮助:)
    • 不客气 :) 我们在这里寻求帮助。不为积分。我首先回答的不是他 :) 你的标签可能处于活动状态,所以你可以在我上方看到他的帖子 :) 但对我来说,你选择谁并不重要 :) 只为你使用最好的标签
    • 哦,对不起,我以为答案是按时间顺序发布的,但我现在明白了。一旦我获得更多经验,我肯定会在几周内回复您的答案,再次感谢!
    【解决方案2】:

    我们可以这样做(原版 JS):

    (本质上,将孩子放入一个数组中,对它们进行排序,然后按照排序后的数组的顺序再次追加它们 - 基本上将它们移动到正确的顺序)

    (排序函数,基本上检查 a 和 b 是否都有可以解析的整数 - 如果有,比较它们,如果它们相等,比较数字后面的字母。如果两者都是字母,则只进行文本比较。如果a 只有字母,b 至少有数字,然后 a 先出现,反之亦然)

    const select = document.querySelector('#models');
    
    [...select.children].sort(mySort).map(node => select.appendChild(node));
    console.log([...select.children]);
    
    function mySort(a,b) {  
      const [a_val, b_val]  = [a.value, b.value];
      
      if (Math.abs(parseInt(a_val) - parseInt(b_val)) >= 0){
        //both are numbers (or at least start with numbers)
        if (parseInt(a_val) - parseInt(b_val) == 0){
          //then we need to compare the letters after too:
          const a_letters = a_val.replace(parseInt(a_val), "");
          const b_letters = b_val.replace(parseInt(b_val), "");
          return a_letters.localeCompare(b_letters)
        } else {
          //the letters after don't matter for comparison:
          return parseInt(a_val) - parseInt(b_val)
        }        
      } else if(Math.abs(parseInt(a_val)) >= 0) {
        //only a is a number, so b goes first:
        return 1;    
      } else if(Math.abs(parseInt(b_val)) >= 0) {
        //only b is a number, so a goes first:
        return -1;    
      } else {
        //both are letters only so do a textual comparison:
        return a_val.localeCompare(b_val)
      }  
        
    }
    <select name="models" id="models">
        <option value="14b">14b</option>
        <option value="ab">ab</option>
        <option value="14">14</option>
        <option value="bc">bc</option>
        <option value="15">15</option>
        <option value="101">101</option>
        <option value="13">13</option>
    </select>

    输出:

    【讨论】:

    • 感谢您抽出宝贵时间回答我的问题,也感谢您将 cmets 添加到您的代码中。由于我对 JavaScript 非常陌生,这有助于我逐步理解您在做什么。对我个人来说,这是完美的!
    • 不客气 :) - 很高兴我能帮上忙。我的建议是在 JQuery 之前掌握 vanilla JS(或者根本不使用 JQuery,如果可以的话)。这样你的基础知识就会更强大,并且更少依赖于库或框架。
    猜你喜欢
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    相关资源
    最近更新 更多