2016-10-20 12 views
8

Tôi đã thử chức năng sắp xếp điển hình và kiểm tra xem mục có phải là chuỗi không. Nhưng tôi nhận được một kết quả rất lạ. Đã thử nhiều cách tiếp cận khác nhau.Sắp xếp mảng các đối tượng có dấu chấm, chữ cái, số. Tôi đã có thể sắp xếp theo số, nhưng giá trị hỗn hợp là khó khăn. Không chắc chắn nếu có thể làm điều đó đúng

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

Tôi có nên sử dụng localeCompare hoặc có thể không? có muốn đầu ra là:

[ 
{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'}] 

nhiều Sẽ đánh giá cao bất cứ đề nghị

Trả lời

3

Bạn có thể chia chuỗi và sử dụng sorting with map, trong khi so sánh từng phần tử của một với mỗi phần tử của một trong những khác. nếu cả hai yếu tố là số, hãy lấy sự khác biệt, nếu không trả về kết quả của localeCompare.

Phần thưởng: Sắp xếp theo số La Mã.

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

+0

Cảm ơn bạn ssoooo nhiều, điều này đã làm việc rất nhiều !! – Prozrachniy

2

Tôi đề nghị một cách tiếp cận hoàn toàn khác nhau. Chúng ta sẽ sửa đổi chuỗi của bạn cho đến khi họ có thể phân loại bởi localeCompare

Đây là cách:

// "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; 
 
};

+0

Cảm ơn rất nhiều! Điều này thật tuyệt! – Prozrachniy

+0

Tuyên bố từ chối: số La Mã sẽ chỉ sắp xếp chính xác nếu chúng xuất hiện ở cuối chuỗi của bạn và thấp hơn IX – user3297291

+0

Điều tôi muốn hiển thị với câu trả lời này là việc triển khai thử nghiệm nhanh chóng có thể giúp bạn đạt được 99% mã đơn giản hơn. Bạn không chắc chắn nếu bạn có thể nhận được với nó trong mã sản xuất, nhưng đó là một bài tập thú vị để làm. Đặc biệt nếu, giống như câu hỏi của bạn, bạn không làm việc với các yêu cầu như một danh sách các thông số kỹ thuật mà là một tập hợp các dữ liệu thử nghiệm ("từ * này * đến * mà *"). – user3297291

Các vấn đề liên quan