iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 17
0
Modern Web

JS30 錄系列 第 17

Day 17 - Sort Without Articles

任務目標

今天要來分類歌單!首先有一串存在陣列中的歌單,我們希望將歌單不考慮 "A" 、 "The" 、 "An" 等冠詞,依照字母 A 至 Z 的順序排列。舉例, "An OTree" 會排在 "The Frog" 後面,因為 "O" 順序在 "F" 後面。

原陣列如下:

const bands = ['The Plot in You', 'The Devil Wears Prada', 'Pierce the Veil', 'Norma Jean', 'The Bled', 'Say Anything', 'The Midway State', 'We Came as Romans', 'Counterparts', 'Oh, Tree', 'A Skylit Drive', 'Anywhere But Here', 'An Old Tree'];

排起來會像這樣。來吧!

作法

思考邏輯如下:

  1. 為了比較去除冠詞後的字串,我們需要一個函式將字串剝皮
  2. 接著利用 Array 的 sort() 方法,依據剝皮字串的順序,來排列原陣列
  3. 最後把排列後的陣列轉換成HTML,放到欲呈現的元素中

使用前幾章累積的招數似乎就能完成了。

首先看第一步,如何撰寫剝皮函式?由於冠詞有 "A" 、 "The" 、 "An" 三種,要在字串中取代重複出現的特定群組,最適合使用正規表達式了!
程式碼如下:

function strip(word) {
  const regex = /^(a|an|the)\s/gi;
  return word.replace(regex, '');
}

正規表達式中, ^ 特殊字元代表「開頭為...」的意思, \s 則代表空白鍵,因此上述正規表達式的意思是:整段字串中,不分大小寫,只要開頭為 "a" 、 "an" 、 "the" ,後面加上空白鍵的,都符合欲搜尋的集合。

將符合條件的字串集合,以 replace 取代成空字串後回傳,自然就得到剝皮後的字串了。

第二步,依照剝皮字串的順序排列原陣列,程式碼如下:

bands.sort((a, b) => strip(a) > strip(b) ? 1 : -1)

sort() 方法在 Day4 有介紹到,用來比較傳入兩值的大小,用回傳數字決定誰先誰後,若結果為 1 ,則 b 會比 a 前面,若 -1 則相反。

在這裡我們是對原陣列 bands 進行排序,比較規則寫在自訂函式中。

在自訂函式中我們比較了剝皮後的字串,對字串做比大小時,會從兩個字串的第一個字元開始,比較該字元在 Unicode 表中的順序,先者為小,後者為大。若兩字元相等,則往後比較,依此類推。舉例: "Otree" 跟 "Oldtree" 相比,第一個字元相同,因此比較第二個字元。"l" 在 Unicode 表中比 "t" 還前面, 因此 "Oldtree" 比 "Otree" 前面。

這跟我們需要的排列規則是相同的,因此在這裡,我們能夠直接用比較運算子來比較剝皮後的字串順序。

第三步,將比較後的結果輸出轉換成HTML格式並輸出到網頁上。 程式碼如下:

const bandsList = document.querySelector('#bands');

bandsList.innerHTML = bands
  .sort((a, b) => strip(a) > strip(b) ? 1 : -1)
  .map(band => {
    return `
      <li>${band}</li>
    `;
  })
  .join('');

map() 複製排序後的陣列,轉換成 <li> 標籤, 用 join() 接起來後,傳到 <ul id="bands"> 這個標籤內即可。

這次感覺像是組合應用前面所學到的知識,難道好日子要來了嗎?

以上就是 JS30 第十七篇!


上一篇
Day 16 - Mouse Move Shadow
下一篇
Day 18 - Adding Up Time With Reduce
系列文
JS30 錄30

尚未有邦友留言

立即登入留言