前言

字典作为最常用的数据结构之一,以键值对的形式存储,最常见的比如像电话簿。字典经常被用来维护某些相对固定的枚举方法或者属性。

字典我们本文使用的是数组作为其基本的数据结构支持,没有使用对象,当然数组也是对象,而对象也是按照字典的基本思路设计的。没有使用基本对象作为其数据结构是因为我们某些场景需要对字典进行排序。

本文源自《数据结构与算法javascript描述》这本书的字典第七章相关章节。

使用场景

对象本身作为字典

在写业务代码的时候,我很多时候看到小伙伴写代码的时候写了过多的具有高度频率重复的一些键值对的对应,或者说if,else的判断。在这种情况下,如果其枚举属性和值比较固定,建议其作为一个枚举字典固定存储和全局使用或者按需使用,这样代码会精简很多。比如:

  1. // old codes
  2. let text = '';
  3. if(status === 1){
  4. text = '没有开课'
  5. } else if(status === 2) {
  6. text = '上课中'
  7. } else {
  8. text = '没有这个课程'
  9. }
  10. // better codes in status.js or enum.js
  11. const statusDict = {
  12. 1:'没有开课'
  13. 2'上课中'
  14. }
  15. const getStatusText = (status) => {
  16. const defaultText = '没有这个课程';
  17. if(!status) return defaultText;
  18. return statusDict[status] || defaultText;
  19. }
  20. // 在vue.js 中有过滤器这样的方法,
  21. //如果你的应用中高频使用一种过滤器,且针对业务较固定,可以考虑定义为全局过滤器,字典结构维护和使用

其他待补充

代码实现

基本定义

因为es6中已经支持了class类,所以我们直接用class语法来实现相关的代码吧,在字典中必有的几个操作,查询,增加,移除,展示。

codepen代码地址:链接

  1. class Dictionary{
  2. constructor(){
  3. this.dataStore = new Array();
  4. this.type = 'Dictionary';
  5. }
  6. find(key){
  7. return this.dataScore[key];
  8. }
  9. add(key, value){
  10. this.dataStore[key] = value ;
  11. }
  12. remove(key){
  13. delete this.dataStore[key];
  14. }
  15. showAll(){
  16. // 这里说明下 for in拿到的是所有对象属性 包括继承来的,而Object.keys仅仅是自身属性
  17. let keys = Object.keys(this.dataStore);
  18. for(var key in keys){
  19. console.log(`${keys[key]}:${this.dataStore[keys[key]]}`);
  20. }
  21. }
  22. }
  23. let numbook = new Dictionary();
  24. numbook.add('mike',1314);
  25. numbook.add('david',98732);
  26. numbook.add('kitty',1314);
  27. numbook.remove("mike");
  28. numbook.showAll();

备注:我们在遍历数组内的所有含有值时,需要用for in遍历,不能用普通的for循环,因为对于数组而言,非数字键的不计入其数组元素。而数组本身也是对象,特殊的是其固定的针对数字键的形成指定顺序的显示与返回。

另外我想说明的是,虽然对象本身就支持较好的字典性质的api,但我们为什么还要额外去定义自己的数据结构呢?因为我们很多时候需要的不是基本api,而是基于某些特定场景下对数据的灵活使用和封装。如果我们对业务代码使用时一个基本的对象字典就够了,当然不用额外定义字典类。但是当某些业务场景下需要我们对字典这种基本api使用的条件下,再做一些额外的功能,那肯定还是需要额外定义自己的字典的。

辅助方法

我们需要实现的辅助方法主要有下面几种。

  1. class Dictionary{
  2. // codes xxx
  3. // 返回具有的个数 ,为什么不用length,因为数组的lenth仅仅针对数字键
  4. count(){
  5. let n = 0 ;
  6. for(let p in Object.keys(this.datastore)){
  7. n++;
  8. }
  9. return n;
  10. }
  11. // 清除所有元素
  12. clear(){
  13. for each (let key in Object.keys(this.dataStore)){
  14. delete this.dataStore[key]
  15. }
  16. }
  17. }

按照顺序显示,前面讲到我们使用数组,主要是因为有排序的需求。那么我们的场景就假设在展示的时候排序即可。

  1. class Dictionary{
  2. // codes xxx
  3. // 返回具有的个数 ,为什么不用length,因为数组的lenth仅仅针对数字键
  4. showAllSort(){
  5. let keys = Object.keys(this.dataStore).sort();
  6. for(var key in keys){
  7. console.log(`${keys[key]}:${this.dataStore[keys[key]]}`);
  8. }
  9. }
  10. }

练习

使用字典的结构,写一个如下的程序,在一段英文文本内,判断出每个单词出现的个数并最终显示出来。

  1. class WordCountDict{
  2. constructor(text){
  3. this.wordDict = {};
  4. this.text = text;
  5. this.init();
  6. }
  7. init(){
  8. let wordArr= this.text.split(' ');
  9. for(let i=0,len=wordArr.length;i<len;i++){
  10. if(wordArr[i] in this.wordDict){
  11. this.wordDict[wordArr[i]]++;
  12. } else {
  13. this.wordDict[wordArr[i]] = 1;
  14. }
  15. }
  16. for(let p in this.wordDict){
  17. console.log(`${p}:${this.wordDict[p]}`)
  18. }
  19. }
  20. }
  21. let text = 'I am a good student and you are a bad one and so on';
  22. let textDict = new WordCountDict(text);