本文由leetcode的字元異位詞分組題目引入,記錄了javascript中對象的鍵的數據類型以及存在的數據類型轉換現象。 ...
題目地址:LeetCode 49. 字母異位詞分組
原題
給你一個字元串數組,請你將 字母異位詞 組合在一起。可以按任意順序返回結果列表。
字母異位詞 是由重新排列源單詞的所有字母得到的一個新單詞。
示例 1:
輸入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"] 輸出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
輸入: strs = [""] 輸出: [[""]]
示例 3:
輸入: strs = ["a"] 輸出: [["a"]]
提示:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i]
僅包含小寫字母
這道題是一道經典的哈希表應用題,哈希表在這道題裡面有兩個應用:
- 對於一個單詞,建立字母到字母出現次數的映射;
- 對於題目給定的單詞數組,需要建立一個 特殊值 到單片語的映射;
其中的 特殊值 應該滿足由單詞計算得到,且不同的字母異位詞的 特殊值 是相同的。
官方題解
/**
* @param {string[]} strs
* @return {string[][]}
*/
var groupAnagrams = function(strs) {
const map = new Object();
for (let s of strs) {
const count = new Array(26).fill(0);
for (let c of s) {
count[c.charCodeAt() - 'a'.charCodeAt()]++;
}
map[count] ? map[count].push(s) : map[count] = [s];
}
return Object.values(map);
};
第一層迴圈遍歷的是片語里的單詞。
for(let s of strs){
const count = new Array(26).fill(0);
...
}
一開始我很疑惑,因為對於每一個單詞,都新建了一個獨立的count
來計算這個單詞中各個字母出現的次數。
這裡的count
就是上文說到的特殊值,用來判斷字母異位詞。
在一個單詞遍歷完所有字母後,count
計算完畢,通過
map[count] ? map[count].push(s) : map[count] = [s];
將 特殊值 相同的單詞分為一組。
我的困惑是每次的count
都是新建的數組,每個單詞的 特殊值 不同,每個單詞都會單獨成組。
但事實是:
JS 對象特性
根據 JS 的語言特性,對象的key
只能是字元串或者Symbol
類型。
count
作為數組類型,在被當作對象的key
使用時,會進行隱式數據類型轉換,被轉換為一個字元串。
於是,只要有一些單詞的字母計數一樣,那麼它們的count
“序列化” 成字元串之後就是相等的。因此,可以被正確地分為一組。
測試
在 Node.js 中測試,使用一個數組作為對象的key
來創建一個鍵值對,輸出對象的keys
發現自動被轉換成字元串了。