4

我有一个包含以下值的数组

asd sdf dsdf 1sadf *sdf !sdf @asdf _asd .sadf (sadf )sadf #sadf 
^asdf &asdf %asdf -sadf =sadf +sadf -sdf

我想按以下方式在javascript中将它分为三个部分。

  1. 以特殊字符开头的单词
  2. 从数字开始的单词
  3. 从字母开始的单词。

所以这应该是排序数组的序列。

编辑:这是我一直在尝试的功能:

function naturalSort(a, b) {
   a = a.path.toLowerCase();
   b = b.path.toLowerCase();
   var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
  sre = /(^[ ]*|[ ]*|[_]*$)/g,
  dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
  hre = /^0x[0-9a-f]+$/i,
  ore = /^0/,
   // convert all to strings and trim()
  x = a.toString().replace(sre, '') || '',
  y = b.toString().replace(sre, '') || '',
   // chunk/tokenize
  xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'),
  yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'),
   // numeric, hex or date detection
  xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
  yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null;
   // first try and sort Hex codes or Dates
   if (yD)
    if (xD < yD) return -1;
    else if (xD > yD) return 1;
   // natural sorting through split numeric strings and default strings
   for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
    // find floats not starting with '0', string or 0 if not defined (Clint Priest)
    oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
    oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
    // handle numeric vs string comparison - number < string - (Kyle Adams)
    if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return (isNaN(oFxNcL)) ? -1 : 1;
    // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
    else if (typeof oFxNcL !== typeof oFyNcL) {
     oFxNcL += '';
     oFyNcL += '';
    }
    if (oFxNcL <= oFyNcL) return -1;
    if (oFxNcL >= oFyNcL) return 1;
   }
   return 0;
  }
4

3 回答 3

21

老实说,我根本不知道您发布的功能是做什么的。

以下方法使用位置出现来比较字符串的第一个字符。具有相同第一个字符的字符串会定期排序。

顺便说一句,没有测试空字符串。

function MySort(alphabet)
{
    return function(a, b) {
        var index_a = alphabet.indexOf(a[0]),
        index_b = alphabet.indexOf(b[0]);

        if (index_a === index_b) {
            // same first character, sort regular
            if (a < b) {
                return -1;
            } else if (a > b) {
                return 1;
            }
            return 0;
        } else {
            return index_a - index_b;
        }
    }
}

var items = ['asd','sdf', 'dsdf', '1sadf', '*sdf', '!sdf', '@asdf', '_asd', '.sadf', '(sadf', ')sadf', '#sadf', '^asdf', '&asdf', '%asdf', '-sadf', '=sadf', '+sadf', '-sdf', 'sef'],
sorter = MySort('*!@_.()#^&%-=+01234567989abcdefghijklmnopqrstuvwxyz');

console.log(items.sort(sorter));

输出:

["*sdf", "!sdf", "@asdf", "_asd", ".sadf", "(sadf", ")sadf", "#sadf", "^asdf", 
 "&asdf", "%asdf", "-sadf", "-sdf", "=sadf", "+sadf", "1sadf", 
 "asd", "dsdf", "sdf", "sef"]
于 2012-06-09T08:48:59.793 回答
3

两个简单的解决方案:

使用 Intl.Collat​​or

myArray.sort(Intl.Collator().compare)

使用 localeCompare

myArray.sort((a, b) => a.localeCompare(b))

Intl.Collat​​or性能更高

于 2021-06-07T02:00:02.783 回答
1

这也可以工作:

function sortArray(a, b) {
  const digitRegex = /^\d/;
  const alphabetRegex = /^[a-zA-Z]/;
  const symbolRegex = /^[^\w\s]/;
  
  const scoreA =  symbolRegex.test(a) * 1 || digitRegex.test(a) * 10 || alphabetRegex.test(a) * 100;
  const scoreB =  symbolRegex.test(b) * 1 || digitRegex.test(b) * 10 || alphabetRegex.test(b) * 100;
  
  if (scoreA !== scoreB) {
    return scoreA - scoreB;
  }
  
  if (a < b) {
    return -1;
  } else if (a > b) {
    return 1;
  }
  
  return 0;
}

const a = ['def', '%rec', '456', '^we', '123', 'abc'].sort(sortArray);

console.log(a);

于 2020-01-31T01:54:51.963 回答