iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0

今日kata

原始題目如下:(6kyu)
You are given an array(list) strarr of strings and an integer k. Your task is to return the first longest string consisting of k consecutive strings taken in the array.

翻譯:
多個長度不同的字串組成陣列,給一整數k,在陣列中必須找到連續k個字串,其字元總長度最長。

範例:

longestConsec(["zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"], 2) --> "abigailtheta"

n being the length of the string array, if n = 0 or k > n or k <= 0 return "".

構想&解法

function longestConsec(strarr, k) {
  if (strarr.length === 0 || k > strarr.length || k <= 0) return ''
  let result = strarr.slice(0, k)
  for (let i = 1; i <= strarr.length - k; i++) {
    let b = strarr.slice(i, k + i)
    result.reduce((acc, cur) => acc + cur, '').length >= b.reduce((acc, cur) => acc + cur, '').length ? result = result : result = b
  }
  return result.reduce((acc, cur) => acc + cur, '')
}

先宣告一result陣列,內容為strarr陣列的前k個元素。
使用for loop產生b陣列strarr.slice(i,k+i)
比較resultb陣列元素的總長度,長度大的為新的result陣列。
繼續下一輪....
最後result的元素總長度就是結果!


其他解法觀摩

function longestConsec(strarr, k) {
  if (k <= 0 || k > strarr.length) {
    return '';
  }
  
  return strarr.reduce((long, item, i) => {
    const currString = strarr.slice(i, i + k).join('');
    return (currString.length > long.length)
      ? currString
      : long;
  }, '');
}

完美使用reduce!
reduce()本身就有迭代的作用,就不用for loop包起來。每一次或每一輪都會產生currString,長度大的當下次的long

每一次迭代都是一個新的block,每一次的常數currString只在自己的block範圍裡,所以沒有問題~


整理用法

看完自己的寫法....reduce只一昧地拿來加總...有點可惜,也不需要,因為使用join()就已經可以加總字串了/images/emoticon/emoticon02.gif


陣列.reduce()

以下內容取自Javascript.info-Array methods

當我們需要一一遍歷陣列進行迭代時,可以使用forEach for 或是 for..of
當我們需要進行迭代的同時又需要回傳data給每一個元素,可以使用map

reduce()也類似,只是它會去計算出一個單一值出來!

語法:arr.reduce(callback( accumulator, currentValue, [, index[, array]] )[, initialValue])
或是簡化一點
let value = arr.reduce(function(accumulator, item, index, array) { // ... }, [initial]);

這個reduce中的function:

  • 每一元素都會執行到
  • 每次都會帶著結果傳給下一輪

參數說明:

  • accumulator 前一輪function執行完的結果,第一輪時,值為initial
  • item 陣列目前遍歷到的元素
  • index 該元素在陣列中的位置
  • array 陣列本身

每一輪function的result都是下一輪的第一個參數accumulator!

範例:

let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((sum, current) => sum + current, 0);
alert(result); // 15

一個加總範例,function傳給reduce兩個參數就夠了sumcurrent

  1. 在第一輪時,sum即為初始值0(reduce的最後一個參數),current為陣列中第一個元素1,所以這個function執行完,結果是1。(這個結果會是下一輪的sum)

  2. 在第二輪時,sum等於1,再把它加上陣列的第二個元素2,並回傳

  3. 在第三輪時,sum等於3,再持續一個一個加上陣列中的元素....

sum current result
第一輪 0 1 1
第二輪 1 2 3
第三輪 3 3 6
第四輪 6 4 10
第五輪 10 5 15

以下寫法的結果還是一樣15,但運作方式不同。當不給初始值時,reduce會取陣列中第一個元素當作初始值,並從第二個元素開始進行迭代 (只遍歷了四次)

let arr = [1, 2, 3, 4, 5];
// removed initial value from reduce (no 0)
let result = arr.reduce((sum, current) => sum + current);
alert( result ); // 1

有無給初始值會影響迭代的起始位置不同,如下圖:
https://ithelp.ithome.com.tw/upload/images/20201008/20128122eXrIXgvyqo.jpg

盡量還是給reduce初始值比較好,以免出現以下的類似錯誤:

let arr = [];
// Error: Reduce of empty array with no initial value
// if the initial value existed, reduce would return it for the empty arr.
arr.reduce((sum, current) => sum + current);

以上為今日分享的內容,若有錯誤或是建議,請再隨時和我聯繫。


上一篇
Valid Parentheses
下一篇
Sum of pairs
系列文
菜鳥工程師的奇幻漂流:跟著kata活化手指和意識30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言