按字母顺序对字符串数组进行排序,然后按特殊字符对数字进行排序

时间:2016-04-17 13:06:23

标签: javascript arrays sorting

鉴于以下字符串数组,我一直在尝试自然地对a-z字符串进行排序,然后是数字字符串,最后是特殊字符。

    nextSearchTerms = ["T","D","I","C","Y","O","4","K","N","800","S","1","V","(","10","'","`","B","M","[","-"," ","J","U","H","G","R","E","P"];
    console.log(nextSearchTerms);

    Array.prototype.naturalSort = function(){
        var a, b, a1, b1, rx=/(\d+)|(\D+)/g, rd=/\d+/;
        return this.sort(function(as, bs){
            a= String(as).toLowerCase().match(rx);
            b= String(bs).toLowerCase().match(rx);
            while(a.length && b.length){
                a1= a.shift();
                b1= b.shift();
                if (rd.test(a1) || rd.test(b1)){
                    if(!rd.test(a1)) return -1;
                    if(!rd.test(b1)) return 1;
                    if(a1 != b1) return a1-b1;
                }
                else if (a1 != b1) {
                    var aIsLetter = a1[0].charAt(0).match(/[a-z]/i),
                        bIsLetter = b1[0].charAt(0).match(/[a-z]/i);
                    if (aIsLetter && !bIsLetter) return -1;
                    if (!aIsLetter && bIsLetter) return 1;
                    return (a1[0] == b1[0] ? 0 : (a1[0] < b1[0] ? -1 : 1));
                }
            }
            return a.length - b.length;
        });
    }
    console.log(nextSearchTerms.naturalSort());

我当前尝试修改的功能返回。

[“B”,“C”,“D”,“E”,“G”,“H”,“I”,“J”,“K”,“M”,“N”,“O” “,”P“,”R“,”S“,”T“,”U“,”V“,”Y“,”“,”'“,”(“,” - “,”[“,” `“,”1“,”4“,”10“,”800“]

我希望最终的数组输出为。

[“B”,“C”,“D”,“E”,“G”,“H”,“I”,“J”,“K”,“M”,“N”,“O” “,”P“,”R“,”S“,”T“,”U“,”V“,”Y“,”1“,”4“,”10“,”800“,”'“, “(”,“ - ”,“[”,“`”,“”]

对我遗失的内容有任何建议吗?

4 个答案:

答案 0 :(得分:2)

这是我对你正在寻找的东西的刺痛。我认为它比你拥有的更清洁:

Array.prototype.naturalSort = function() {
  var stringRE = /^[A-Za-z]+$/
  var numberRE = /^[\d]+$/
  return this.sort(function(a, b) {
    var aIsString = stringRE.test(a);
    var bIsString = stringRE.test(b)
    var aIsNumeric = numberRE.test(a);
    var bIsNumeric = numberRE.test(b);
    if (aIsString && bIsString) {
      return a.localeCompare(b);
    } else if (aIsNumeric && bIsNumeric) {
      return parseInt(a, 10) - parseInt(b, 10);
    } else if (aIsString && bIsNumeric) {
      return -1;
    } else if (aIsNumeric && bIsString) {
      return 1;
    } else if (aIsString || aIsNumeric) {
      return -1;
    } else if (bIsString || bIsNumeric) {
      return 1;
    } else {
      return a.localeCompare(b);
    }
  })
};

var chars = ["T","D","I","C","Y","O","4","K","N","800","S","1","V","(","10","'","`","B","M","[","-"," ","J","U","H","G","R","E","P"];

console.log(chars.naturalSort());
// ["B", "C", "D", "E", "G", "H", "I", "J", "K", "M", "N", "O", "P", "R", "S", "T", "U", "V", "Y", "4", "1", "10", "800", " ", "-", "'", "(", "[", "`"]

答案 1 :(得分:0)

这个怎么样?将某些内容与数字进行比较...

            if (rd.test(a1) || rd.test(b1)){
                var aIsLetter = a1[0].charAt(0).match(/[a-z]/i),
                    bIsLetter = b1[0].charAt(0).match(/[a-z]/i);
                if(!rd.test(a1) && aIsLetter) return -1;
                if(!rd.test(a1) && !aIsLetter) return 1;
                if(!rd.test(b1) && bIsLetter) return 1;
                if(!rd.test(b1) && !bIsLetter) return -1;
                if(a1 != b1) return a1-b1;
            }

答案 2 :(得分:0)

这是一个较短的解决方案:

function naturalSort(a, b) {
  var aPriority = /[a-z]/i.test(a) * 3 + /\d+/i.test(a) * 2; 
  var bPriority = /[a-z]/i.test(b) * 3 + /\d+/i.test(b) * 2; 

  if (aPriority === bPriority) return a.localeCompare(b, 'en', {numeric: true});
  return aPriority < bPriority ? 1: -1;
}

nextSearchTerms.sort(naturalSort)
// ["B", "C", "D", "E", "G", "H", "I", "J", "K", "M", "N", "O", "P", "R", "S", "T", "U", "V", "Y", "1", "4", "10", "800", " ", "-", "'", "(", "[", "`"]

如果我理解正确,这应该回答你的要求。它很简单易懂。字母有更高的优先级(3),数字有2,其余有1。数组按优先顺序排序。

LE:修正数字排序;

答案 3 :(得分:-1)

我想以下方法将完成所请求的任务。实际上,该功能只是一个单线程,它利用了可链接的数组功能。为了更好地理解,我将其分为三行。按以下步骤操作;

  1. 将数组缩减为由3个不同类型的数组组成的数组。这样做时会将小数转换为数字,因为下一步将需要它。
  2. 通过对类型数组进行排序来减少数组,如果它们是数字类型并且与前一个数据类型相连,则将它们映射回字符串。
  3. 我相信它可以进一步简化,但到目前为止,我能想出的是什么。请指教......

    &#13;
    &#13;
    var testar = ["T","D","I","C","Y","O","4","K","N","800","S","1","V","(","10","'","`","B","M","[","-"," ","J","U","H","G","R","E","P", "0", "-17"];
    function naturalSort(a){
      return a.reduce((p,c) => {
                                 /[A-Z]/i.test(c) ? p[0].push(c)   :
                                 /\d+/.test(c)    ? p[1].push(c*1) : p[2].push(c);
                                 return p
                               }, [[],[],[]])
              .reduce((p,c) => p.concat(c.sort((p,c) => p < c ? -1:1)
              .map(e => typeof e == "number" ? e.toString() : e)),[]);
    }
    document.write('<pre>' + JSON.stringify(naturalSort(testar), 0, 2) + '</pre>');
    &#13;
    &#13;
    &#13;