iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
0
自我挑戰組

菜鳥工程師的奇幻漂流:跟著kata活化手指和意識系列 第 9

Counting Duplicates

今日kata

原始題目如下:(6kyu)
Write a function that will return the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string. The input string can be assumed to contain only alphabets (both uppercase and lowercase) and numeric digits.

翻譯:
不用區分大小寫,找出字串中重複的字母有幾種 (非次數)

範例:
"abcde" -> 0 # 沒有字母重複
"aabbcde" -> 2 # 'a' 和 'b'
"aabBcde" -> 2 # 'a' 和 'b' 都出現兩次 (b and B算一種字母)
"indivisibility" -> 1 # 'i' 重複出現


構想&解法

function duplicateCount(text) {
  let arr = text.split('').map(item => item.toUpperCase())
  result = arr.reduce((obj, item) => {
    obj[item] === undefined ? obj[item] = 1 : obj[item]++;
    return obj
  }, {})
  
  let count = 0
  Object.keys(result).forEach(key => {
    if (result[key] > 1) count++
  });
  return count
}

A,a都算同一種,自然先把每個字母統一轉成大寫or小寫,再來是無處不在的reduce,目的是要統計各個字母的出現次數。

Ex:

// APPLE
{
    'A':1,
    'P':2,
    'L':1,
    'E':1
}
// key為字母
// value為該字母的出現次數

設定初始值為一個空物件obj{},每遍歷到新的元素/字母item,檢查物件中是否已有key存在。
例如一開始物件為空時,第一次傳入A這個item,檢查obj[A] === undefined ? 物件中A這個key沒有賦值,於是執行obj[item] = 1,如果已經有存在A這個key,則執行obj[item]++,最後建立出Object,內容是各個字母的出現次數。


其他解法

function duplicateCount(text){
  return (text.toLowerCase().split('').sort().join('').match(/([^])\1+/g) || []).length;
}

如同上一篇整理的字串常用方法,toLowerCase()split()join()match()

拆解/([^])\1+/g正規表示式:

  • ([^]):第一組
    • [^]:任一字元 ([^A]代表非A以外的所有字元)
    • []:比對其中項目
  • \1+ :符合第一組
    • +:出現1次以上
  • g :搜尋整個字串

Ex:aabbc,會有兩個符合結果aabb

翻譯:每一個字元由左至右開始檢測,[^]代表任一字元都會變成一組,檢查是否和後面的字元相同,符合一次以上就算match!


function duplicateCount(text){
  return text.toLowerCase().split('').filter(function(val, i, arr){
    return arr.indexOf(val) !== i && arr.lastIndexOf(val) === i;
  }).length;
}

利用arr.filter根據每一個字元在原始字串中的位置,判斷是否出現兩次以上。

Ex:aabbc,經過filter方法:

  • val依序為a,a,b,b,c,i為index,arr為aabbc
  • aabbc中a的第一次出現位置為0;最後一次為1
  • arr.indexOf(val) !== i && arr.lastIndexOf(val) === i
    意思為:留下的元素須符合array第一次出現該元素的位置非自己本身的位置&array最後一次出現該元素的位置為自己目前的位置。繞口令無誤.....

整理用法

陣列.filtter()

語法:let newArray = arr.filter(callback(element[, index, [array]])[, thisArg])

filter要傳入一function,每一個arr的元素都會被經過測試。Return true的才會保留該元素,最後結果會回傳一新的陣列。(function有三個參數element、index、array可使用)

範例:

let age=[1,3,6,8,12,5,45,77,30]
let result= age.filter((ele,index,arr)=>ele>18)
// result=[45,77,30]

Object.keys(物件)

語法:Object.keys(obj)

回傳物件中可列舉(enumerable)之屬性組成的陣列。

範例:

const object1={
    a:'i',
    b:'love',
    c:'my',
    d:'job'
}
console.log(Object.keys(object1))
// ['a','b','c','d']

有關列舉不可列舉&物件屬性細節,會再用一篇說明~~/images/emoticon/emoticon02.gif

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


上一篇
Decode the Morse code
下一篇
Who likes it?
系列文
菜鳥工程師的奇幻漂流:跟著kata活化手指和意識30

尚未有邦友留言

立即登入留言