2015-08-24 38 views
0

我有一個巨大的比較函數,我正在使用數字和字符串值對二維數組進行排序,並且我想讓它變小。我已經在對方內部重複使用了相同的代碼塊,我認爲這是多餘的。我想我可以使用遞歸來縮小代碼,但是我不認爲我之前做過這些,而且我的排序功能似乎非常複雜。這是如下:排序函數中的遞歸

check if a & b is array 
check if a & b is number or string 
    if number 
     check if a equals to b 
      repeat same process with different index 
    if string 
     check if a equals to b 
      repeat same process with different index 

一個例子數組:

var artists = [ 
    ["Katy Perry",   "3", "9"  ], 
    ["Enrique Iglesias", "3", "9"  ], 
    ["Taylor Swift",  "2", "9"  ], 
    ["Evanescence",   "4", "10" ], 
    ["Bruno Mars",   "1", "5"  ], 
    ["Shania Twain",  "3", "12" ], 
    ["Amanda Abizaid",  "2", "2"  ], 
    ["Death Cab For Cutie", "2", "2"  ], 
    ["Simple Plan",   "1", "2"  ], 
]; 

// sort and prioritize columns by 2, 1, 0, sort order for each 1 = asc 
artists.sort(compare.bind([2, 1, 0], [1, 1, 1])); 

排序後的同一個陣列:

var artists = [ 
    ["Simple Plan",   "1", "2"  ], 
    ["Amanda Abizaid",  "2", "2"  ], 
    ["Death Cab For Cutie", "2", "2"  ], 
    ["Bruno Mars",   "1", "5"  ], 
    ["Taylor Swift",  "2", "9"  ], 
    ["Enrique Iglesias", "3", "9"  ], 
    ["Katy Perry",   "3", "9"  ], 
    ["Evanescence",   "4", "10" ], 
    ["Shania Twain",  "3", "12" ], 
]; 

實際比較功能:

// compare is passed to Array.prototype.sort 
// array2bSorted.sort(sortable.compare.bind([cols, orders])); 

compare : function(a, b) { 

    var columns = sortable.explodeInnerArrays(this[0]); 
    var orders = sortable.explodeInnerArrays(this[1]); 

    var primaryA = a[columns[0]]; 
    var primaryB = b[columns[0]]; 

    if (primaryA instanceof Array) { 
     primaryA = a[columns[0]][0]; 
    } 
    if (primaryB instanceof Array) { 
     primaryB = b[columns[0]][0]; 
    } 

    switch (sortable.checkDataType(primaryA)) { 
     case "number": 
      if (primaryA == primaryB && columns.length > 1) { 

       var secondaryA = a[columns[1]]; 
       var secondaryB = b[columns[1]]; 

       if (secondaryA instanceof Array) { 
        secondaryA = a[columns[1]][0]; 
       } 
       if (secondaryB instanceof Array) { 
        secondaryB = b[columns[1]][0]; 
       } 

       switch (sortable.checkDataType(secondaryA)) { 
        case "number": 
         if (secondaryA == secondaryB && columns.length > 2) { 

          var tertiaryA = a[columns[2]]; 
          var tertiaryB = b[columns[2]]; 

          if (tertiaryA instanceof Array) { 
           tertiaryA = a[columns[2]][0]; 
          } 
          if (tertiaryB instanceof Array) { 
           tertiaryB = b[columns[2]][0]; 
          } 

          switch (sortable.checkDataType(tertiaryA)) { 
           case "number": 
            return (tertiaryA - tertiaryB) * orders[2]; 
            break; 
           case "string": 
            tertiaryA = sortable.removePunctuation(tertiaryA); 
            tertiaryB = sortable.removePunctuation(tertiaryB); 
            if (tertiaryA < tertiaryB) { 
             return -1 * orders[2]; 
            } 
            if (tertiaryA > tertiaryB) { 
             return 1 * orders[2]; 
            } 
            return 0; 
            break; 
          } 
         } 
         return (secondaryA - secondaryB) * orders[1]; 
         break; 
        case "string": 
         if (secondaryA == secondaryB && columns.length > 2) { 

          var tertiaryA = a[columns[2]]; 
          var tertiaryB = b[columns[2]]; 

          if (tertiaryA instanceof Array) { 
           tertiaryA = a[columns[2]][0]; 
          } 
          if (tertiaryB instanceof Array) { 
           tertiaryB = b[columns[2]][0]; 
          } 

          switch (sortable.checkDataType(tertiaryA)) { 
           case "number": 
            return (tertiaryA - tertiaryB) * orders[2]; 
            break; 
           case "string": 
            tertiaryA = sortable.removePunctuation(tertiaryA); 
            tertiaryB = sortable.removePunctuation(tertiaryB); 
            if (tertiaryA < tertiaryB) { 
             return -1 * orders[2]; 
            } 
            if (tertiaryA > tertiaryB) { 
             return 1 * orders[2]; 
            } 
            return 0; 
            break; 
          } 
         } 
         secondaryA = sortable.removePunctuation(secondaryA); 
         secondaryB = sortable.removePunctuation(secondaryB); 
         if (secondaryA < secondaryB) { 
          return -1 * orders[1]; 
         } 
         if (secondaryA > secondaryB) { 
          return 1 * orders[1]; 
         } 
         break; 
       } 
      } 
      return (primaryA - primaryB) * orders[0]; 
      break; 
     case "string": 
      if (primaryA == primaryB && columns.length > 1) { 

       var secondaryA = a[columns[1]]; 
       var secondaryB = b[columns[1]]; 

       if (secondaryA instanceof Array) { 
        secondaryA = a[columns[1]][0]; 
       } 
       if (secondaryB instanceof Array) { 
        secondaryB = b[columns[1]][0]; 
       } 

       switch (sortable.checkDataType(secondaryA)) { 
        case "number": 
         if (secondaryA == secondaryB) { 

          var tertiaryA = a[columns[2]]; 
          var tertiaryB = b[columns[2]]; 

          if (tertiaryA instanceof Array) { 
           tertiaryA = a[columns[2]][0]; 
          } 
          if (tertiaryB instanceof Array) { 
           tertiaryB = b[columns[2]][0]; 
          } 

          switch (sortable.checkDataType(tertiaryA)) { 
           case "number": 
            return (tertiaryA - tertiaryB) * orders[2]; 
            break; 
           case "string": 
            tertiaryA = sortable.removePunctuation(tertiaryA); 
            tertiaryB = sortable.removePunctuation(tertiaryB); 
            if (tertiaryA < tertiaryB) { 
             return -1 * orders[2]; 
            } 
            if (tertiaryA > tertiaryB) { 
             return 1 * orders[2]; 
            } 
            return 0; 
            break; 
          } 
         } 
         return (secondaryA - secondaryB) * orders[1]; 
         break; 
        case "string": 
         if (secondaryA == secondaryB && columns.length > 2) { 

          var tertiaryA = a[columns[2]]; 
          var tertiaryB = b[columns[2]]; 

          if (tertiaryA instanceof Array) { 
           tertiaryA = a[columns[2]][0]; 
          } 
          if (tertiaryB instanceof Array) { 
           tertiaryB = b[columns[2]][0]; 
          } 

          switch (sortable.checkDataType(tertiaryA)) { 
           case "number": 
            return (tertiaryA - tertiaryB) * order; 
            break; 
           case "string": 
            tertiaryA = sortable.removePunctuation(tertiaryA); 
            tertiaryB = sortable.removePunctuation(tertiaryB); 
            if (tertiaryA < tertiaryB) { 
             return -1 * orders[2]; 
            } 
            if (tertiaryA > tertiaryB) { 
             return 1 * orders[2]; 
            } 
            return 0; 
            break; 
          } 
         } 
         secondaryA = sortable.removePunctuation(secondaryA); 
         secondaryB = sortable.removePunctuation(secondaryB); 
         if (secondaryA < secondaryB) { 
          return -1 * orders[1]; 
         } 
         if (secondaryA > secondaryB) { 
          return 1 * orders[1]; 
         } 
         break; 
       } 

      } 
      primaryA = sortable.removePunctuation(primaryA); 
      primaryB = sortable.removePunctuation(primaryB); 
      if (primaryA < primaryB) { 
       return -1 * orders[0]; 
      } 
      if (primaryA > primaryB) { 
       return 1 * orders[0]; 
      } 
      break; 
    } 
}, 

比較函數對數組由多列組成每個都有自己的排序順序。由於列以數組形式傳遞,因此初始索引具有更高的優先級。

Working fiddle

使用遞歸我已經想出了下面的代碼,但它不工作。數組未排序。它也不會拋出任何錯誤。 (我刪除了一些不相關的部分,使它看起來更簡單)

compare : function(a, b) { 

    var columns = sortable.explodeInnerArrays(this[0]); 
    var orders = sortable.explodeInnerArrays(this[1]); 

    function loop(a, b, index) { 

     var currentA = a[columns[index]]; 
     var currentB = b[columns[index]]; 

     switch (sortable.checkDataType(currentA)) { 
      case "number": 
       if (currentA == currentB) { 
        loop(a, b, (index+1)); 
       } 
       return (currentA - currentB) * orders[index]; 
       break; 
      case "string": 
       if (currentA == currentB) { 
        loop(a, b, (index+1)); 
       } 
       if (currentA < currentB) { 
        return -1 * orders[index]; 
       } 
       if (currentA > currentB) { 
        return 1 * orders[index]; 
       } 
       break; 
     } 
    } 

    loop(a,b,0); 
} 

我缺少什麼?

+0

是的,明確的。遞歸或循環。無論如何,您需要支持3列以上。你試過了嗎? – Bergi

+0

@Bergi是的,仍然在努力。嘗試遞歸。我不知道我會如何去循環。 – akinuri

+0

如果這不僅僅是爲了教育目的,爲什麼不使用Array.prototype.sort()方法?這是從IE> = 5.5支持的,當然也支持所有現代Web瀏覽器。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort –

回答

0

我設法解決了這個問題,並創建了我的第一個遞歸。

簡單地調用loop函數內部compare,因爲它返回1-1compare功能和compare功能不返回任何東西沒有做任何事情。我需要返回loop函數返回的值。 return loop(a, b, index)做到了。

compare : function(a, b) { 

    var columns = sortable.explodeInnerArrays(this[0]); 
    var orders = sortable.explodeInnerArrays(this[1]); 

    function loop(a, b, index) { 

     var currentA = a[columns[index]]; 
     var currentB = b[columns[index]]; 

     if (currentA instanceof Array) { 
      currentA = a[columns[index]][0]; 
     } 
     if (currentB instanceof Array) { 
      currentB = b[columns[index]][0]; 
     } 

     switch (sortable.checkDataType(currentA)) { 
      case "number": 
       if (currentA == currentB) { 
        return loop(a, b, (index+1)); 
       } 
       return (currentA - currentB) * orders[index]; 
       break; 
      case "string": 
       if (currentA == currentB) { 
        return loop(a, b, (index+1)); 
       } 
       currentA = sortable.removePunctuation(currentA); 
       currentB = sortable.removePunctuation(currentB) 
       if (currentA < currentB) { 
        return -1 * orders[index]; 
       } 
       if (currentA > currentB) { 
        return 1 * orders[index]; 
       } 
       break; 
     } 
    } 

    return loop(a, b, 0); 
} 
-1

我已經在if和switch語句中多次使用了相同的代碼塊,我認爲這是多餘的。

試圖跳進遞歸之前,先嚐試重構:先用Extract Method到重複的代碼移動到其自身的功能。

+0

只有這樣才行。 – akinuri