4 kyu
跟之前解過的一題類似,也是把秒數轉換為人類看懂的時間。
格式是:年/日/時/分/秒,並且用英文輸出。
例如:12 days, 5 hours, 38 minutes and 23 seconds。
有兩件大任務,時間 & 字串顯示方式。
分析時間可參考過去看到的最佳解:
把時間用大一階的方式取餘,剩下的就是該時間的數值。
例如:seconds / 60 % 60
,先以六十取得以分鐘為單位,再以每小時 60 分,
取得的餘數,也就是分鐘單位的數值,因為多餘的時間將會在取整時被省略。
將時間以 key 單位,用物件拆分,再轉成陣列方便調用。
用 object.entries 轉換成陣列,並驗證陣列長度;只保留 value > 0 的元素,並且如果 value 大於 1,keys + s。
Object.entries(times).filter(item =>{
if(item[1]>1) item[0] = item[0]+"s";
return item[1] !== 0
})
switch:
=1
直接返回
=2
用 and 拼接後返回
=3
第一元素key+,,最後尾元素前安插and
=3up
除了倒數兩個元素外每個都key +,,最後尾元素前安插and
function formatDuration(seconds) {
if (seconds === 0) return "now";
let times = {}
if (seconds > 80000) {
times["year"] = parseInt(seconds / 60 / 60 / 24 / 365);
}
times["day"] = parseInt(seconds / 60 / 60 / 24 % 365);
times["hour"] = parseInt(seconds / 60 / 60 % 24);
times["minute"] = parseInt(seconds / 60 % 60);
times["second"] = parseInt(seconds % 60);
let workArr = Object.entries(times).filter(item => {
if (item[1] > 1) item[0] = item[0] + "s";
item = item.reverse();
return item[0] !== 0
})
switch (workArr.length) {
case 1:
return workArr.flat().join(" ");
break;
case 2:
workArr.splice(1, 0, "and");
return workArr.flat().join(" ");
break;
case 3:
workArr[0][1] = workArr[0][1] + ",";
workArr.splice(workArr.length - 1, 0, "and");
return workArr.flat().join(" ");
break;
default:
workArr = workArr.map((item, index, array) => {
if (index < array.length - 2) item[1] = item[1] + ",";
})
workArr.splice(workArr.length - 1, 0, "and");
return workArr.flat().join(" ");
break;
}
}
如果秒數過小年份的計算可能會有誤差;因此加一個秒數判斷,在秒數大於一定程度時才計算以年為單位的時間。
其次分別計算出各個單位的時間後,以 Object.entries 形式將物件轉換為:[[”單位”: 單位的值],…]
格式;使用陣列方法 filter 過濾掉值為 0 的時間單位,並且如果值大於 1,則單位就添加 s 的複數字尾。
switch 帶入的是陣列長度,也就是最後輸出字串時總共有幾個時間單位。
並且依照規律,將 ,
補充在對應的位置、利用 splice 插入 and
,最終都是將陣列平面化後轉成字串。
function formatDuration (seconds) {
var time = { year: 31536000, day: 86400, hour: 3600, minute: 60, second: 1 },
res = [];
if (seconds === 0) return 'now';
for (var key in time) {
if (seconds >= time[key]) {
var val = Math.floor(seconds/time[key]);
res.push(val += val > 1 ? ' ' + key + 's' : ' ' + key);
seconds = seconds % time[key];
}
}
return res.length > 1 ? res.join(', ').replace(/,([^,]*)$/,' and'+'$1') : res[0]
}
這個方法預先把每一個時間單位的 1 的秒數都寫成 time 物件。
並用 for…in 來跑物件的迴圈,比對如果秒數大於等於該單位,則取商並用 Math.floor 取整。
最後 push 到 res 陣列中,並利用取得的 val 以及迭代的 key 拼接單位以及判斷是否加 s。
seconds 則取餘之後再進入下一輪。
最後判斷儲存結果的 res 長度是否大於 1?
如果大於 1:物件內容以 ,
輸出成字串後,使用取代功能查找,正則表達式會捕獲最後一個 ,
之後的字串。
舉例如果是字串 “3 years, 62 days, 9 hours, 46 minutes, 40 seconds”
,
會捕獲的是 “ 40 seconds”
,用意是在拼接最後的 and。
即使單位只有兩個,因為先以 ,
拼接整個字串了,多餘的逗號都會被取代掉。
如果三元運算子 res 長度不大於一,表示只有一個單位,直接輸出即可。
貌似這是最簡單的 4 kyu 題目,不過確實是越來越燒腦了。
其實 5 kyu 就有非常多有趣的邏輯題,可以感受出來歐美那邊對於邏輯方面的學科頗有歷史。
今天是中秋,中秋節快樂!