7

我正在尝试使用 javascript 中动态创建的 SELECT OPTIONS 列表。

我无法访问源代码,否则我会从服务器代码中更改它。

这是选择:

<select class="text12 width_constrained" name="/web/personalisation/request/DesignConsultationRequestFormHandler.addressItem">
<option value="1|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">1 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="3|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">3 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="5|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">5 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="7|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">7 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="9|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">9 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="11|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">11 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="13|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">13 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="15|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">15 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="17|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">17 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="19|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">19 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="21|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">21 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="23|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">23 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="25|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">25 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="27|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">27 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="2|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">2 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="4|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">4 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="6|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">6 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="8|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">8 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="10|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">10 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="12|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">12 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="14|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">14 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="16|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">16 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="18|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">18 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="20|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">20 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="22|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">22 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="24|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">24 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="26|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">26 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>
<option value="28|Marsh Gardens||Southampton, Hedge End|Hampshire|SO30 2XN|United Kingdom|false|false|false|false|false|false|false">28 Marsh Gardens, Southampton, Hedge End, SO30 2XN</option>

我目前正在使用以下内容,但它仅使用自然排序按第一个字符排序,不支持字母数字...

jQuery('document').ready(function() {
var opts = jQuery('form[name=consultationForm] select option');

console.log("options");
console.log(opts);

var arr = opts.map(function(_, o) {
    return {
        t: jQuery(o).text(),
        v: o.value
    };
}).get();

console.log("options post sort");
//arr.sort();


arr.sort(function(o1, o2) {
    return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0;
});

console.log(arr);

});

显而易见的期望输出是让所有选项按数值排序,但也允许子集,例如 2a、2b、2c。

任何人都可以提供进一步的帮助吗?

4

6 回答 6

11

听起来你想要的是自然排序,我在这里找到了这个代码示例:Javascript:字母数字字符串的自然排序 这将为 2a、2b、2c 之类的值以及没有门牌号的值提供正确的排序。

function naturalSorter(as, bs){
    var a, b, a1, b1, i= 0, n, L,
    rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
    if(as=== bs) return 0;
    a= as.toLowerCase().match(rx);
    b= bs.toLowerCase().match(rx);
    L= a.length;
    while(i<L){
        if(!b[i]) return 1;
        a1= a[i],
        b1= b[i++];
        if(a1!== b1){
            n= a1-b1;
            if(!isNaN(n)) return n;
            return a1>b1? 1:-1;
        }
    }
    return b[i]? -1:0;
}

然后

arr.sort(function(o1, o2) {
    return naturalSorter(o1.t, o2.t);
});

我稍微编辑了 TJ 的小提琴来举个例子:JSFiddle

于 2013-10-08T14:22:59.863 回答
1

您的字符串可能已转换为数字,因为它们以数字开头。您可以尝试以下排序功能:

arr.sort(function(o1, o2) {
    return o1.t.localeCompare(o2.t);
});

有关更多信息,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

于 2013-10-08T12:26:01.130 回答
1

如果使用得当,我相信localeSort应该做你想做的事。如果由于某种原因,您需要实现自己的排序比较,请尝试以下操作:

arr.sort(function(o1, o2) { 
    return o1.t.split(/(\d+|\D+)/)[1] - o2.t.split(/(\d+|\D+)/)[1] 
} );

创建一个交替的split数字和非数字字符串数组(它们之间有空字符串,我们可以为此忽略)。数组的元素 0 是空的,所以元素 1 是第一个组件 - 门牌号,没有多余的字符会使数字转换器将其视为NaN. 减法强制将字符串转换为数字,您就可以开始了。

通过根据需要检查每个字符串,该想法可以推广到完全自然的排序:

arr.sort(function(o1, o2) {
           var a = o1.t.split(/(\d+|\D+)/).filter(function(s){return s!=""});
           var b = o2.t.split(/(\d+|\D+)/).filter(function(s){return s!=""});
           for (var cmp = 0, i = 0; 0 == cmp && i < a.length && i < b.length; i++) {
             var n1 = a[i] - 0, n2 = b[i] - 0;
             if (!isNaN(n1) && !isNaN(n2)) 
               cmp = n1 - n2;
             else if (a[i] < b[i]) 
               cmp = -1;
             else if (a[i] > b[i])
               cmp = 1;
           }
           return cmp;
         })
于 2013-10-08T12:44:48.113 回答
0

我创建了一个小提琴来演示重新排序。我将valueandtext属性的值以及解析的街道号码存储在一个数组中。没有排序更容易。有人可能会争辩说我的代码有点臃肿,可能有一种更优雅的方式。

$(document).ready(function () {

    var selectModel = []; // We use this to store all the option data

    $('select.text12 option').each(function () {
        var $this = $(this);
        selectModel.push({
            value: $this.val(),
            text: $this.text(),
            index: parseInt($this.val().split('|')[0], 10) // Make sure it's a number
        });
    });

    selectModel.sort(function (a, b) {
        return a.index - b.index;
    });

    var tempHtml = '';

    for (var i = 0, ii = selectModel.length; i < ii; i++) {
        tempHtml += '<option value="' + selectModel[i].value + '">' + selectModel[i].text + '</option>';
    }

    // Here the option html is recreated
    $('select.text12').html(tempHtml);

});
于 2013-10-08T13:09:09.150 回答
0

万一有人想要一个不包含正则表达式的排序算法。我认为它更快,但尚未测试过。

function alphanum(a, b) {
  function chunkify(t) {
    var tz = [], x = 0, y = -1, n = 0, i, j;

    while (i = (j = t.charAt(x++)).charCodeAt(0)) {
      var m = (i == 46 || (i >=48 && i <= 57));
      if (m !== n) {
        tz[++y] = "";
        n = m;
      }
      tz[y] += j;
    }
    return tz;
  }

  var aa = chunkify(a);
  var bb = chunkify(b);

  for (x = 0; aa[x] && bb[x]; x++) {
    if (aa[x] !== bb[x]) {
      var c = Number(aa[x]), d = Number(bb[x]);
      if (c == aa[x] && d == bb[x]) {
        return c - d;
      } else return (aa[x] > bb[x]) ? 1 : -1;
    }
  }
  return aa.length - bb.length;
}

小提琴。_

于 2015-06-01T19:09:37.027 回答
0

我修改了脚本以使用对象(按对象属性自然排序)

代码

function alphanumCase(a, b, prop) {
    function chunkify(t) {
        var tz = new Array();
        var x = 0, y = -1, n = 0, i, j;

        while (i = (j = t.charAt(x++)).charCodeAt(0)) {
            var m = (i == 46 || (i >=48 && i <= 57));
            if (m !== n) {
                tz[++y] = "";
                n = m;
            }
            tz[y] += j;
        }
        return tz;
    }

    var aa = chunkify(a[prop].toLowerCase());
    var bb = chunkify(b[prop].toLowerCase());

    for (x = 0; aa[x] && bb[x]; x++) {
        if (aa[x] !== bb[x]) {
            var c = Number(aa[x]), d = Number(bb[x]);
            if (c == aa[x] && d == bb[x]) {
                return c - d;
            } else return (aa[x] > bb[x]) ? 1 : -1;
        }
    }
    return aa.length - bb.length;
}

用法

someArray.sort(function(a, b) {
    //sort naturally by the name property (a.name vs b.name)
    return alphanumCase(a, b, 'name');
});
于 2016-09-05T13:02:13.910 回答