Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Codewars 練習 07:Extract Range

問題

將陣列中的數字,有連續整數的情況用連字號 (-) 連接起來。舉例來說 [1,2,3] 會變成 '1-3'。其中需要特別注意的是只有連續兩個整數時,不用連接。

我的解法

function solution(list){
  let temp = 0;
  return list.reduce( ( acc, cur, curI, arr ) => {
      if ( cur === arr[curI-1] + 1 && cur === arr[curI+1] -1 ) {
        temp++;
        return acc;
      } else if( temp > 0 ) {
        temp = 0;
        return acc + '-' + cur;
      } else {
        temp = 0;
        return acc + ',' + cur;
      }
  } );
}

在原本的構想中 temp 這個變數的目的,是用來判斷是否是連續 3 個數字,當 temp 大於 0 的時候,代表前一步已經是符合「前後都有」的情境,因此便會是連續 3 個整數。

票選最佳解法

function solution2(individualIntegers) {
  return individualIntegers
    .reduce(splitIntoRanges, [])
    .map(convertToRange)
    .join(",");
}

function splitIntoRanges(ranges, number) {
  if (!ranges.length) {
    ranges.push([number]);
    return ranges;
  }

  var lastRange = ranges[ranges.length - 1];
  var lastNumber = lastRange[lastRange.length - 1];

  number === lastNumber + 1 ? lastRange.push(number) : ranges.push([number]);
  return ranges;
}

function convertToRange(range) {
  return range.length < 3 ? range.join(",") : range[0] + "-" + range[range.length - 1];
}

其他解

function solution3(list){
   for(var i = 0; i < list.length; i++){
      var j = i;
      while(list[j] - list[j+1] == -1) j++;
      if(j != i && j-i>1) list.splice(i, j-i+1, list[i] +'-'+list[j]);
  }
  return list.join();
}

改善點

票選的最佳解中,是透過拆分函式的方式,用 convertToRange() 來判斷是否為連續數字,整體作法上比較像是我最早嘗試的方向。

另外一種解法,則是先透過 var j = i,讓 list[j] 可以快速到每個區間的最大值,接著再用 splice() 的方式減去陣列中介於區間的值,再來串接每個頭尾字串。執行上效能最好。

這次我可能太執著於 Array.reduce() 的作法,所以試了蠻久才把結果試出來。下面附上當初測試邏輯時的完整程式碼。

function solution(list){
 // TODO: complete solution 
  let temp = 0;
  return list.reduce( ( acc, cur, curI, arr ) => {
        console.log( 'acc is: ' + acc );
        console.log( 'cur is: ' + cur );
        console.log( 'arr[curI-1] +1 is ' + (arr[curI-1] + 1) );
        console.log( 'arr[curI+1] -1 is ' + (arr[curI+1] - 1) );
        if ( cur === arr[curI-1] + 1 && cur === arr[curI+1] -1 ) {
        console.log( 'both true' );
        temp++;
        return acc.toString();
        } else if( cur === arr[curI - 1] + 1 && temp > 0 ) {
        console.log( 'one true' );
        temp = 0;
        return acc.toString() + '-' + cur.toString();
        } else {
        console.log( 'false' );
        temp = 0;
        return acc.toString() + ',' + cur.toString();
        }
  } );
}
Eric Chuang
Eric Chuang

正職是廣告行銷人員,因為 Google Tag Manager 的關係開始踏入網站製作的領域,進一步把 WordPress 當成 PHP + HTML + CSS + JavaScript 的學習教材。此外,因為工作的關係,曾經用 Automattic 的 Underscores (_s) 替客戶與公司官網進行全客製化佈景主題開發。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料