讀古今文學網 > 學習JavaScript數據結構與算法(第2版) > 7.1 字典 >

7.1 字典

你已經知道,集合表示一組互不相同的元素(不重複的元素)。在字典中,存儲的是[鍵,值]對,其中鍵名是用來查詢特定元素的。字典和集合很相似,集合以[值,值]的形式存儲元素,字典則是以[鍵,值]的形式來存儲元素。字典也稱作映射。

在本章中,我們會介紹幾個在現實問題上使用字典數據結構的例子:一個實際的字典(單詞和它們的釋義)以及一個地址簿。

7.1.1 創建字典

Set類相似,ECMAScript 6同樣包含了一個Map類的實現,即我們所說的字典。

我們在本章中將要實現的類就是以ECMAScript 6中Map類的實現為基礎的。你會發現它和Set類很相似(但不同於存儲[值,值]對的形式,我們將要存儲的是[鍵,值]對)。

這是我們的Dictionary類的骨架:

function Dictionary {
  var items = {};
}

  

Set類類似,我們將在一個Object的實例而不是數組中存儲元素。

然後,我們需要聲明一些映射/字典所能使用的方法。

  • set(key,value):向字典中添加新元素。

  • delete(key):通過使用鍵值來從字典中移除鍵值對應的數據值。

  • has(key):如果某個鍵值存在於這個字典中,則返回true,反之則返回false

  • get(key):通過鍵值查找特定的數值並返回。

  • clear:將這個字典中的所有元素全部刪除。

  • size:返回字典所包含元素的數量。與數組的length屬性類似。

  • keys:將字典所包含的所有鍵名以數組形式返回。

  • values:將字典所包含的所有數值以數組形式返回。

  • hasset方法

    我們首先來實現has(key)方法。之所以要先實現這個方法,是因為它會被setremove等其他方法調用。我們可以通過如下代碼來實現:

    this.has = function(key) {
      return key in items;
    };
    
      

    這個方法的實現和我們之前在Set類中的實現是一樣的。我們使用JavaScript中的in操作符來驗證一個key是否是items對象的一個屬性。

    然後是set方法的實現:

    this.set = function(key, value) {
      items[key] = value; //{1}
    };
    
      

    該方法接受一個key和一個value作為參數。我們直接將value設為items對象的key屬性的值。它可以用來給字典添加一個新的值,或者用來更新一個已有的值。

  • delete方法

    接下來,我們實現delete方法。它和Set類中的delete方法很相似,唯一的不同點在於我們將先搜索key(而不是value):

    this.delete= function(key) {
      if (this.has(key)) {
        delete items[key];
        return true;
      }
      return false;
    };
    
      

    然後我們可以使用JavaScript的remove操作符來從items對像中移除key屬性。

  • getvalues方法

    如果我們想在字典中查找一個特定的項,並檢索它的值,可以使用下面的方法:

    this.get = function(key) {
      return this.has(key) ? items[key] : undefined;
    };
    
      

    get方法首先會驗證我們想要檢索的值是否存在(通過查找key值),如果存在,將返回該值,反之將返回一個undefined值(請記住undefined值和null值是不一樣的,第1章中提到過這個概念)。

    下一個是values方法。這個方法以數組的形式返回字典中所有values實例的值:

    this.values = function {
      var values = ;
      for (var k in items) { //{1}
        if (this.has(k)) {
          values.push(items[k]); //{2}
        }
      }
      return values;
    };
    
      

    首先,我們遍歷items對象的所有屬性值(行{1})。為了確定值存在,我們使用has函數來驗證key確實存在,然後將它的值加入values數組(行{2})。最後,我們就能返回所有找到的值。

     我們不能僅僅使用 for-in語句來遍歷items對象的所有屬性,還需要使用hasOwnProperty方法(驗證items對象是否包含某個屬性),因為對象的原型也會包含對象的其他屬性(JavaScript基本的Object類中的屬性將會被繼承,並存在於當前對像中,而對於這個數據結構來說,我們並不需要它們)。

  • clearsizekeysgetItems方法

    clearsize方法與第6章Set類中對應的方法是完全一樣的,因此我們就不在本章討論了。

    keys方法返回在Dictionary類中所有用於標識值的鍵名。要取出一個JavaScript對像中所有的鍵名,可以把這個對象作為參數傳入Object類的keys方法(到目前為止,書中創建的類,包括Dictionary在內,都是JavaScript對像),如下:

    this.keys = function {
      return Object.keys(items);
    };
    
      

    最後,我們來驗證items屬性的輸出值。我們可以實現一個返回items變量的方法,叫作getItems

    this.getItems = function {
      return items;
    }
    
      

7.1.2 使用Dictionary

首先,我們來創建一個Dictionary類的實例,然後給它添加三條電子郵件地址。我們將會使用這個dictionary實例來實現一個電子郵件地址簿。

使用我們創建的類來執行如下代碼:

var dictionary = new Dictionary;
dictionary.set(\'Gandalf\', \'[email protected]\');
dictionary.set(\'John\', \'[email protected]\');
dictionary.set(\'Tyrion\', \'[email protected]\');

  

如果執行了如下代碼,輸出結果將會是true

console.log(dictionary.has(\'Gandalf\'));

  

下面的代碼將會輸出3,因為我們向字典實例中添加了三個元素:

console.log(dictionary.size);

  

現在,執行下面的幾行代碼:

console.log(dictionary.keys);
console.log(dictionary.values);
console.log(dictionary.get(\'Tyrion\'));

  

輸出結果分別如下所示:

    [\"Gandalf\", \"John\", \"Tyrion\"]
    [\"[email protected]\", \"[email protected]\", \"[email protected]\"]
    [email protected]

  

最後,再執行幾行代碼:

dictionary.delete(\'John\');

  

再執行下面的代碼:

console.log(dictionary.keys);
console.log(dictionary.values);
console.log(dictionary.getItems);

  

輸出結果如下所示:

[\"Gandalf\", \"Tyrion\"]
[\"[email protected]\", \"[email protected]\"]
Object {Gandalf: \"[email protected]\", Tyrion:
\"[email protected]\"}

  

移除了一個元素後,現在的dictionary實例中只包含兩個元素了。加粗的一行表現了items對象的內部結構。