排序数组对象与点,字母,数字.我能按数字排序,但混合值很难排序.不确定是否有可能做对



我尝试了典型的排序函数并检查了项目是否为字符串。但是我得到一个很奇怪的输出。试过很多不同的方法

 var arr = [{section: '12.2.a'},
               {section: '12.2.b.iii'},
               {section: '12.2.c'},
               {section: '12'},
               {section: '12A'},
               {section: '12.3.b'},
               {section: '12.3.c'},
               {section: 'Q2'},
               {section: 'Q32'},
               {section: 'Q6'},
               {section: 'Q5'}]

var arr2 = arr.sort(function(a, b) {
    var nums1 = a.section.split(".");
    var nums2 = b.section.split(".");
    for (var i = 0; i < nums1.length; i++) {
      if (nums2[i]) {
        if (nums1[i] !== nums2[i]) {
          if (isNaN(parseInt(nums1[i])) && isNaN(parseInt(nums2[i]))) {
            return nums1[i].localeCompare(nums2[i]);
          }
          return parseInt(nums1[i]) - parseInt(nums2[i]);   
        }
      } else {
        return 1;
      }
    }
    return -1;
});

我应该使用localeCompare还是可以不使用?希望输出为:

[
 {section: '12'},
 {section: '12A'},
 {section: '12.2.a'},
 {section: '12.2.b.iii'},
 {section: '12.2.c'},
 {section: '12.3.b'},
 {section: '12.3.c'},
 {section: 'Q2'},
 {section: 'Q6'},
 {section: 'Q5'}
 {section: 'Q32'}]

非常感谢您的建议

我提出一个完全不同的方法。我们将修改您的字符串,直到它们可以通过localeCompare

进行排序

方法如下:

// "12" sorts before "2", prefixing to "12" and "02" fixes this
// (length should be bigger than your largest nr)
var makeLength5 = prefixWithZero.bind(null, 5);
// This function generates a string that is sortable by localeCompare
var toSortableString = function(obj) {
  return obj.section
    .replace(/./g, "z")            // Places `12A` before `12.` but after `12`
    .replace(/d+/g, makeLength5);  // Makes every number the same length
};
var arr = [{section:"12.2.a"},{section:"12.2.b.iii"},{section:"12.2.c"},{section:"12"},{section:"12A"},{section:"12.3.b"},{section:"12.3.c"},{section:"Q2"},{section:"Q32"},{section:"Q6"},{section:"Q5"}];
var arr2 = arr.sort(function(a, b) {
  return toSortableString(a).localeCompare(toSortableString(b));
});
console.log(JSON.stringify(arr2.map(function(s){ return s.section; }), null, 2));
// Helper methods
function prefixWithZero(length, str) {
  while (str.length < length) {
    str = "0" + str;
  }
  return str;
};

您可以拆分字符串并使用map排序,同时将其中的每个元素与另一个中的每个元素进行比较。如果两个元素都是数字,取差值,否则返回localeCompare的结果。

附加功能:用罗马数字排序。

function customSort(data, key, order) {
    function isNumber(v) {
        return (+v).toString() === v;
    }
    function isRoman(s) {
        // http://stackoverflow.com/a/267405/1447675
        return /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/i.test(s);
    }
    function parseRoman(s) {
        var val = { M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1 };
        return s.toUpperCase().split('').reduce(function (r, a, i, aa) {
            return val[a] < val[aa[i + 1]] ? r - val[a] : r + val[a];
        }, 0);
    }
    var sort = {
            asc: function (a, b) {
                var i = 0,
                    l = Math.min(a.value.length, b.value.length);
                while (i < l && a.value[i] === b.value[i]) {
                    i++;
                }
                if (i === l) {
                    return a.value.length - b.value.length;
                }
                if (isNumber(a.value[i]) && isNumber(b.value[i])) {
                    return a.value[i] - b.value[i];
                }
                if (isRoman(a.value[i]) && isRoman(b.value[i])) {
                    return parseRoman(a.value[i]) - parseRoman(b.value[i]);
                }
                return a.value[i].localeCompare(b.value[i]);
            },
            desc: function (a, b) {
                return sort.asc(b, a);
            }
        },
        mapped = data.map(function (el, i) {
            var string = el[key].replace(/d(?=[a-z])|[a-z](?=.)/gi, '$&. .'),
                regex = /(d+)|([^0-9.]+)/g,
                m,
                parts = [];
            while ((m = regex.exec(string)) !== null) {
                parts.push(m[0]);
            }
            return { index: i, value: parts, o: el, string: string };
        });
    mapped.sort(sort[order] || sort.asc);
    return mapped.map(function (el) {
        return data[el.index];
    });
}
var arr = [{ section: '12.2.a' }, { section: '12.2.b.viii' }, { section: '12.2.b.xi' }, { section: '12.2.b.x' }, { section: '12.2.b.ix' }, { section: '12.2.b.vii' }, { section: '12.2.b.vi' }, { section: '12.2.b.iv' }, { section: '12.2.b.v' }, { section: '12.2.b.ii' }, { section: '12.2.b.iii' }, { section: '12.2.b.i' }, { section: '12.2.b.iii' }, { section: '12.2.c' }, { section: '12' }, { section: '12A' }, { section: '12.3.b' }, { section: '12.3.c' }, { section: 'Q2' }, { section: 'Q32' }, { section: 'Q6' }, { section: 'Q5' }, { section: 'Q.10' }, { section: 'Q.1' }, { section: 'Q.2' }];
console.log('sorted array asc', customSort(arr, 'section'));
console.log('sorted array desc', customSort(arr, 'section', 'desc'));
console.log('original array', arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }

最新更新