資料結構之字典入門
字典作為最常用的資料結構之一,以鍵值對的形式儲存,最常見的比如像電話簿。字典經常被用來維護某些相對固定的列舉方法或者屬性。
字典我們本文使用的是陣列作為其基本的資料結構支援,沒有使用物件,當然陣列也是物件,而物件也是按照字典的基本思路設計的。沒有使用基本物件作為其資料結構是因為我們某些場景需要對字典進行排序。
本文源自《資料結構與演算法javascript描述》這本書的字典第七章相關章節。
使用場景
物件本身作為字典
在寫業務程式碼的時候,我很多時候看到小夥伴寫程式碼的時候寫了過多的具有高度頻率重複的一些鍵值對的對應,或者說if,else的判斷。在這種情況下,如果其列舉屬性和值比較固定,建議其作為一個列舉字典固定儲存和全域性使用或者按需使用,這樣程式碼會精簡很多。比如:
// old codes let text = ''; if(status === 1){ text = '沒有開課'; } else if(status === 2) { text = '上課中' } else { text = '沒有這個課程'; } // better codes in status.js or enum.js const statusDict = { 1:'沒有開課', 2:'上課中', } const getStatusText = (status) => { const defaultText = '沒有這個課程'; if(!status) return defaultText; return statusDict[status] || defaultText; } // 在vue.js 中有過濾器這樣的方法, //如果你的應用中高頻使用一種過濾器,且針對業務較固定,可以考慮定義為全域性過濾器,字典結構維護和使用 複製程式碼
其他待補充
程式碼實現
基本定義
因為es6中已經支援了class類,所以我們直接用class語法來實現相關的程式碼吧,在字典中必有的幾個操作,查詢,增加,移除,展示。
codepen程式碼地址:連結
class Dictionary{ constructor(){ this.dataStore = new Array(); this.type = 'Dictionary'; } find(key){ return this.dataScore[key]; } add(key, value){ this.dataStore[key] = value ; } remove(key){ delete this.dataStore[key]; } showAll(){ // 這裡說明下 for in拿到的是所有物件屬性 包括繼承來的,而Object.keys僅僅是自身屬性 let keys = Object.keys(this.dataStore); for(var key in keys){ console.log(`${keys[key]}:${this.dataStore[keys[key]]}`); } } } let numbook = new Dictionary(); numbook.add('mike',1314); numbook.add('david',98732); numbook.add('kitty',1314); numbook.remove("mike"); numbook.showAll(); 複製程式碼
備註:我們在遍歷陣列內的所有含有值時,需要用for in遍歷,不能用普通的for迴圈,因為對於陣列而言,非數字鍵的不計入其陣列元素。而陣列本身也是物件,特殊的是其固定的針對數字鍵的形成指定順序的顯示與返回。
另外我想說明的是,雖然物件本身就支援較好的字典性質的api,但我們為什麼還要額外去定義自己的資料結構呢?因為我們很多時候需要的不是基本api,而是基於某些特定場景下對資料的靈活使用和封裝。如果我們對業務程式碼使用時一個基本的物件字典就夠了,當然不用額外定義字典類。但是當某些業務場景下需要我們對字典這種基本api使用的條件下,再做一些額外的功能,那肯定還是需要額外定義自己的字典的。
輔助方法
我們需要實現的輔助方法主要有下面幾種。
class Dictionary{ // codes xxx // 返回具有的個數 ,為什麼不用length,因為陣列的lenth僅僅針對數字鍵 count(){ let n = 0 ; for(let p in Object.keys(this.datastore)){ n++; } return n; } // 清除所有元素 clear(){ for each (let key in Object.keys(this.dataStore)){ delete this.dataStore[key] } } } 複製程式碼
按照順序顯示,前面講到我們使用陣列,主要是因為有排序的需求。那麼我們的場景就假設在展示的時候排序即可。
class Dictionary{ // codes xxx // 返回具有的個數 ,為什麼不用length,因為陣列的lenth僅僅針對數字鍵 showAllSort(){ let keys = Object.keys(this.dataStore).sort(); for(var key in keys){ console.log(`${keys[key]}:${this.dataStore[keys[key]]}`); } } } 複製程式碼
練習
使用字典的結構,寫一個如下的程式,在一段英文文字內,判斷出每個單詞出現的個數並最終顯示出來。
class WordCountDict{ constructor(text){ this.wordDict = {}; this.text = text; this.init(); } init(){ let wordArr= this.text.split(' '); for(let i=0,len=wordArr.length;i<len;i++){ if(wordArr[i] in this.wordDict){ this.wordDict[wordArr[i]]++; } else { this.wordDict[wordArr[i]] = 1; } } for(let p in this.wordDict){ console.log(`${p}:${this.wordDict[p]}`) } } } let text = 'I am a good student and you are a bad one and so on'; let textDict = new WordCountDict(text); 複製程式碼