在JavaScript中对数组进行字母数字排序

在JavaScript中对数组进行字母数字排序,javascript,jquery,Javascript,Jquery,我试图使用javascript中动态创建的选择选项列表 我没有访问源代码的权限,否则我会从服务器代码中更改它 这是选择: <select class="text12 width_constrained" name="/web/personalisation/request/DesignConsultationRequestFormHandler.addressItem"> <option value="1|Marsh Gardens||Southampton, Hedge En

我试图使用javascript中动态创建的选择选项列表

我没有访问源代码的权限,否则我会从服务器代码中更改它

这是选择:

<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>

1马什花园,南安普敦,树篱端,SO30 2XN
3马什花园,南安普敦,树篱端,SO30 2XN
5马什花园,南安普敦,树篱端,SO30 2XN
7马什花园,南安普敦,树篱端,SO30 2XN
9马什花园,南安普敦,树篱端,SO30 2XN
11马什花园,南安普敦,Hedge End,SO30 2XN
13 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
15马什花园,南安普敦,树篱端,SO30 2XN
17 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
19 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
21马什花园,南安普敦,Hedge End,SO30 2XN
23马什花园,南安普敦,树篱端,SO30 2XN
25 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
27 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
2马什花园,南安普敦,树篱端,SO30 2XN
4马什花园,南安普敦,树篱端,SO30 2XN
6马什花园,南安普敦,树篱端,SO30 2XN
8马什花园,南安普敦,树篱端,SO30 2XN
10 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
12 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
14马什花园,南安普敦,树篱端,SO30 2XN
16马什花园,南安普敦,Hedge End,SO30 2XN
18 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
20 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
22 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
24马什花园,南安普敦,树篱端,SO30 2XN
26 Marsh Gardens,南安普敦,Hedge End,SO30 2XN
28 Marsh Gardens,南安普敦,Hedge End,SO30 2XN

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

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);

});
jQuery('document').ready(函数(){
var opts=jQuery('form[name=consultationForm]select option');
控制台日志(“选项”);
控制台日志(opts);
var arr=opts.map(函数{
返回{
t:jQuery(o).text(),
v:o值
};
}).get();
log(“选项后排序”);
//arr.sort();
arr.sort(功能(o1,o2){
返回o1.t>o2.t-1:o1.t
显然,期望的输出是所有选项按数值排序,但也允许子集,例如2a、2b、2c


有人能提供进一步的帮助吗?

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

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

有关更多信息,请参阅。

我认为
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;
         })
arr.sort(函数(o1,o2){
var a=o1.t.split(/(\d+\d+/).filter(函数){returns!=“”});
var b=o2.t.split(/(\d+\d+/).filter(函数){returns!=“”});
对于(var cmp=0,i=0;0==cmp&&ib[i])
cmp=1;
}
返回cmp;
})
我创建了一个示例来演示重新订购。我将
文本
属性的值以及解析的街道编号存储在一个数组中。不,排序更容易。 有人可能会说我的代码有点臃肿,可能有一种更优雅的方式

$(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);

});
$(文档).ready(函数(){
var selectModel=[];//我们使用它来存储所有选项数据
$('select.text12 option')。每个(函数(){
var$this=$(this);
选择model.push({
值:$this.val(),
text:$this.text(),
index:parseInt($this.val().split(“|”)[0],10)//确保它是一个数字
});
});
选择model.sort(功能(a、b){
返回a.index-b.index;
});
var tempHtml='';
对于(变量i=0,ii=selectModel.length;i
听起来您想要的是自然排序,我在这里找到了这个代码示例:这将为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;
}

我稍微编辑了TJ的fiddle以给出一个例子:

以防任何人想要一个不包含正则表达式的排序算法。我想它会更快,但还没有测试过

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;
}
函数alphanum(a,b){
功能组块化(t){
var tz=[],x=0,y=-1,n=0,i,j;
而(i=(j=t.charAt(x++).charCodeAt(0)){
var m=(i==46 | |(i>=48&&i bb[x])?1:-1;
}
}
返回aa.length-bb.length;
}

.p>我修改了脚本以处理对象(按对象属性自然排序)

代码
考虑使用分裂。你的意思是:“但也允许子集,例如2a,2b,2c。”所以地址是“1沼泽园”、“2沼泽园”……你可以有“1沼泽园”、“2A沼泽园”、“2B沼泽园”。当我尝试实现这个时,我遇到了一个错误:Uncaught TypeError:Object#没有“localeCompare”方法对不起,忘记了
t
键。将它添加到示例中。这是
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;
}
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');
});