# 字典(Dictionary)

类似于集合, 字典也是一种无重复元素, 无顺序的数据结构。

区别在于在集合中, 我们以 [值, 值] 的形式存储; 在字典中, 我们以 [键, 值] 的形式存储;

ES6 引入的 Map 就是字典的数据类型。

方法 描述
set 添加新元素, 如果存在则覆盖值
remove 移除键值
hasKey 键值是否存在 (Boolean)
get 获取指定键值
clear 清除字典
size 返回字典数量
isEmpty 字典数量是否为空 (Boolean)
keys 返回所有键名 (Array)
values 返回所有键值 (Array)
keyValues 将字典所有[键, 值]对返回 (Array)
forEach 迭代字典中所有的键值对 call(key, value)

# 实现

class ValuePair {
    constructor(key, value) {
        this.key = key
        this.value = value
    }
    toString() {
        return `[${this.key}: ${this.key}]`
    }
}
class Dictionary {
    constructor() {
        this.toStrFn = function(item) {
            if (item === null) {
                return 'NULL'
            } else if (item === undefined) {
                return 'UNDEFINED'
            } else if (typeof item === 'string' || item instanceof String) {
                return `${item}`                
            } else {
                item.toString()
            }
        }
        this.table = {}
    }

    set(key, value) {
        if (key != null && value != null) {
            const tableKey = this.toStrFn(key)
            this.table[tableKey] = new ValuePair(key, value)
            return true
        }
        return false
    }

    remove(key) {
        if (this.hasKey(key)) {
            delete this.table[this.toStrFn(key)]
            return true
        }
        return false
    }

    get(key) {
        const valuePair = this.table[this.toStrFn(key)]
        return valuePair == null ? undefined : valuePair.value
    }

    hasKey(key) {
        return this.table[this.toStrFn(key)] != null
    }

    keyValues() {
        const valuePair = []
        for (let k in this.table) {
            if (this.hasKey(k)) {
                valuePair.push(this.table[k])
            }
        }
        return valuePair
    }

    keys() {
        const keys = []
        const valuePairs = this.keyValues()
        for (let i = 0; i < valuePairs.length; i++) {
            keys.push(valuePairs[i].key)
        }
        return keys
    }

    values() {
        const values = []
        const valuePairs = this.keyValues()
        for (let i = 0; i < valuePairs.length; i++) {
            values.push(valuePairs[i].value)
        }
        return values
    }

    size() {
        return this.keys().length
    }

    isEmpty() {
        return this.size() === 0
    }

    clear() {
        this.table = {}
    }    

    forEach(callFn) {
        const valuePairs = this.keyValues()
        for (let i = 0; i < valuePairs.length; i++) {
            const key = valuePairs[i].key,
                  value = valuePairs[i].value,
                  result = callFn(key, value);
            // 如果回调函数返回false 则中断forEach方法的执行
            if (result === false) {
                break;
            }
        }
    }
}