記一次JavaScript API練習題

以前,我在Codewars上看到一道名爲Recover a secret string from random triplets的題,這道題使我沉思了好久,最終在朋友的幫助下我完成了這個題目。當我完成這個題目而且看到其餘大神的答案時, 我就以爲我真的頗有必要記錄一下這道題,而且思考它在JavaScript中的實現。前端

這道題目的大概意思是講:有一個密碼字符串存在,而你會得到這個密碼字符串的隨機三個字符的集合,根據這個集合你須要還原出這個密碼字符串。
已知:
1.密碼字符串中不會出現重複的字母
2.這個集合包含了足能夠推斷出密碼字符串的信息
3.密碼字符串不會不包含集合中的字母正則表達式

英文好的朋友能夠看下面的原文題幹,題目做者解釋的比我清楚:數組

There is a secret string which is unknown to you. Given a collection
of random triplets from the string, recover the original string.dom

A triplet here is defined as a sequence of three letters such that each letter occurs somewhere before the next in the given string.

"whi" is a triplet for the string "whatisup".函數

As a simplification, you may assume that no letter occurs more than once in the secret string.
You can assume nothing about the triplets given to you other than that they are valid triplets and that they contain sufficient

information to deduce the original string. In particular, this means
that the secret string will never contain letters that do not occur in
one of the triplets given to you.學習

也能夠經過一個例子來理解題目:this

secret1 = "whatisup"    // 密碼字符串-->程序的輸出
triplets1 = [           // 集合 --> 程序的輸入
  ['t','u','p'],
  ['w','h','i'],
  ['t','s','u'],
  ['a','t','s'],
  ['h','a','p'],
  ['t','i','s'],
  ['w','h','s']
]
var recoverSecret = function(triplets) {
// ... -->程序的實現
}

我認爲這道題目作起來很舒服,雖然答案並非第一時間很快就寫出來的,可是題幹清楚簡單就免除了閱讀理解的煩擾也是杜絕了因爲題意冗長 理解不到位形成了程序錯誤。並且實現方法也多種多樣,在作完答案後看看大神的最佳實踐也是一種享受。code

下面是個人解決方案:
首先,列出集合中全部的字母,由於集合和密碼字符串中的字母種類是一致且無重複的,因此只須要把列出的全部字母去重就能夠獲得密碼字符串的無序排列。regexp

triplets1 = [           // 原集合
  ['t','u','p'],
  ['w','h','i'],
  ['t','s','u'],
  ['a','t','s'],
  ['h','a','p'],
  ['t','i','s'],
  ['w','h','s']
]

triplets2 =['t','u','p',  // 列出的全部集合字母
'w','h','i','t','s','u',
'a','t','s','h','a','p',
't','i','s','w','h','s']

triplets3 =['t','u','p','w','h','i','s','a']  // 去重後的集合 無序字符串

而後咱們再根據原集合給出的排列規則將無序字符串進行排列,而經過觀察,我發現原集合中每一個小數組之間的順序關係太過繁雜甚至有的小數組之間都沒有順序關係(好比 triplets1[0] 和 triplets1[1] ),那麼最方便實現的解決辦法就是隻顧及每一個小數組三個字母之間的順序關係:orm

['t','u','p'] // 粗體--> 第一個小數組的第一個順序關係
['t','u','p','w','h','i','s','a'] // 找到 't' 和 'u' 發現順序正確
['t','u','p'] // 粗體--> 第一個小數組的第二個順序關係
['t','u','p','w','h','i','s','a'] // 找到 'u' 和 'p' 發現順序正確
['w','h','i'] // 粗體--> 第二個小數組的第一個順序關係
['t','u','p','w','h','i','s','a'] // 找到 'w' 和 'h' 發現順序正確
['w','h','i'] // 粗體--> 第二個小數組的第二個順序關係
['t','u','p','w','h','i','s','a'] // 找到 'h' 和 'i' 發現順序正確
['t','s','u'] //粗體--> 第三個小數組的第一個順序關係
['t','u','p','w','h','i','s','a'] // 找到 't' 和 's' 發現順序不正確
['s','u','p','w','h','i','t','a'] // 交換位置
// ...依次類推,最後的結果是
['w','t','a','h','p','i','u','s']

很明顯能夠看到只根據一次的比較還不足以獲得結果的順序,因此咱們要外套一個循環,繼續使用原集合的順序信息繼續排序,直到所有排序完成輸出答案。

下面是我JavaScript的程序實現:

const recoverSecret =(triplets)=> {
let result = ""
//  排列集合字符串 去重
  for(let i=0; i < triplets.length; i++){      
    for(let j = 0; j < triplets[i].length; j++){
      if (result.indexOf(triplets[i][j]) == -1){
        result += triplets[i][j]
      }
    }
  }
 // 用於標識while大循環是否進行
  var flag = true
  while(flag){
  flag = false
   for(let i = 0; i < triplets.length; i++){
     for(let j = 0; j < 2; j++){
       if (result.indexOf(triplets[i][j]) > result.indexOf(triplets[i][j+1])){
         flag = true
// 給交換字母位置
         result = result.replace(triplets[i][j], triplets[i][j+1]).replace(triplets[i][j+1], triplets[i][j])
       }
     }
   }
   }
  return result
}

代碼中用到的API比較少,差很少爲如下兩個:

String.indexOf(searchValue)
方法返回調用String對象中第一次出現的指定值的索引,開始在 fromIndex進行搜索。
searchValue表示被查找的值

String.replace(regexp, substr)
方法返回一個由替換值替換一些或全部匹配的模式後的新字符串。模式能夠是一個字符串或者一個正則表達式, 替換值能夠是一個字符串或者一個每次匹配都要調用的函數。
regexp表示要被替換的字符串
substr表示替換的字符串

*以上API資料來源於MDN

最後我要說 這個題目還遠遠沒有完,而它的迷人之處就在於它不止一個解決辦法,若是你沒有思路,能夠在Codewars上粘貼我上面的代碼並提交(這樣你才能夠看到別人的答案)研究大神的解決方案就會發現它的魅力。觸類旁通,多多思考,多多實踐纔是學習前端的最佳實踐。

相關文章
相關標籤/搜索