2016-07-28 53 views
0

我想對從文檔中提取的某些段落號進行排序。Nodejs:對段落號進行排序

不幸的是,他們並不是真正的小數所以標準sort功能不起作用。例如,我想要以下結果:["3.1","3.2","3.11"]不是["3.1","3.11","3.2"](這是我從使用中得到的結果:http://www.w3schools.com/jsref/jsref_sort.asp)。

的數字也有小數數量不確定。例如,他們可能會出現如下:["1.i.a","1.i.b","1.i.c.A","1.i.c.B"]

在處理這個問題一段時間後,我認爲最好的解決方案是將每個數字視爲由'。'分隔的子字符串,並根據'最低'子字符串。

任何人都可以提出如何在JS做什麼?

任何幫助深表感謝

+0

你永遠不需要比較一個數字和一個字母,是正確的嗎?例如,'3.4'和'3.a'永遠不需要比較? – apsillers

+1

有些想法:你的子串是數字,在這種情況下,排序很簡單,或者它們是字母。在這種情況下,您可以嘗試執行查找表來對其進行編號轉換。唯一的問題將是羅馬數字('I','IV' ...),除非您找到一種方法可靠地將它們與簡單字母區分開來。 – DrakaSAN

+0

@apsillers - 是的,這是正確的。所有的子字符串將是相同的類型。 – qts

回答

1

這是否適合您?如果需要,我可以提供更多解釋。

"use strict" 
let index = ['3.1.a', '3.2', '3.11', '3.1.c', '3.2.z']; 

index.sort((a, b) => { 
    var aArr = a.split('.'), bArr = b.split('.') 

    for (var i = 0, aLength = aArr.length; i < aLength; i++) { 
    let aVal = aArr[i], bVal = bArr[i] 
    if (!isNaN(aVal)) aVal = Number(aVal) // convert substring into Number if it is a Number 
    if (!isNaN(bVal)) bVal = Number(bVal) 

    if (bVal === undefined) return 1 // b lower index 
    if (aVal === bVal) continue 

    return typeof(aVal) === "string" ? aVal.charCodeAt() - bVal.charCodeAt() : aVal - bVal; // for strings, works only if length == 1 
    } 

    return bArr[i] === undefined ? 0 : -1 // if b undefined, then both numbers are equal, otherwise a is shorter 
}) 

console.log(index) 
// outputs [ '3.1.a', '3.1.c', '3.2', '3.2.z', '3.11' ] 
+0

你能幫我理解這段代碼嗎?我一直在使用它幾個星期,並發現它對羅馬數字不能100%工作(例如'3.1.a.vi',3.1.a.iv')。另外,當我控制檯登錄輸出,aVal - bVal返回字母'NaN' – qts

+0

你是對的,這裏的代碼不適用於字母。我可以爲此添加一點修正。對於羅馬數字,這是一個前衛的例子,因爲沒有辦法區分它和普通字母。以下是我的建議:如果一個子字符串對應一個羅馬數字,它將被視爲一個羅馬數字(例如,如果您有3.4.i,它將被轉換爲3.4.1)。你怎麼看? – jonathanGB

+1

@qts我已經修復了答案,所以它可以正確使用字母。現在,它只會在子字符串只是一個字母時才起作用。這可以嗎? – jonathanGB

0

一個不完整的,相當嚴格的方式做到這一點可能是這樣的:

'use strict'; 

const async = require('async'); 

let index = ['3.1.a', '3.2', '3.11', '3.1.c', '3.2.z']; 

//'3.1.a' => ['3', '1', 'a'] 
function paragraphToSubstring(string, callback) { 
    async.map(string, (s, callback) => { 
     callback(null, s.split('.')); 
    }, (err, substrings) => { 
     callback(substrings); 
    }); 
} 

//['3', '1', 'a'] => [3, 1, 1] 
function substringToNumber(substrings) { 
    async.map(substrings, (e, callback) { 
     let i = parseInt(e); 
     //If e is a letter 
     if(isNaN(i)) { 
      //Take it's ASCII value 
      //If you need to support roman number, you'll have to make the check and transformation here 
      callback(null, e.charCodeAt(0)); 
     } else { 
      callback(null, i); 
     } 
    }) 
} 

function sort(paragraphs, callback) { 
    async.waterfall([ 
     //Convert everything in array 
     (callback) => { 
      async.map(paragraphs, (p, callback) => { 
       paragraphToSubstring(p, (s) => { 
        callback(null, s); 
       }); 
      }, (err, substrings) => { 
       callback(err, substrings) 
      }); 
     }, 
     //Convert everything in numbers 
     (substrings, callback) => { 
      async.map(substrings, (s, callback) => { 
       substringToNumber(s, (err, i) => { 
        callback(err, i); 
       }); 
      }, (err, numbers) => { 
       callback(err, numbers); 
      }); 
     } 
     //Sort 
     (numbers, callback) => { 
      callback(null, numbers.sort((a, b) => { 
       //Didn't found a way to support a undefinite number of element, settled on 3 
       let s1 = a[0] - b[0], 
        s2 = a[1] - b[1], 
        s3 = a[2] - b[2]; 

       if(s1) { 
        return s1; 
       } 
       if(s2) { 
        return s2; 
       } 
       if(s3) { 
        return s3; 
       } 
      })); 
     } 
    ], (err, sorted) { 
     callback(err, sorted); 
    }); 
} 

有趣的練習做,我會回來以後有好轉,當我還得有更多的工作時間。

+0

我認爲這太過於浪費了haha – jonathanGB

+0

@jonathanGB:可能我沒有考慮到性能,更多的是關於可讀性和處理每一個可能的錯誤。 – DrakaSAN

+0

爲什麼是異步?這裏沒有I/O或ajax? – jonathanGB

相關問題