【问题标题】:I want to implement the hashtable in javascript but it has an exception我想在 javascript 中实现哈希表,但它有一个例外
【发布时间】:2017-08-22 08:46:39
【问题描述】:
function HashTable(){
    var size = 0;
    var entry = new Object();
    this.add = function(key,value){
        if(!containsKey(key)){
            size++;
        }
        entry[key] = value;
    }

    this.getValue = function(key){
        return containsKey(key)?entry[key]:null;
    }

    this.remove = function(key){
        if (containsKey(key) && delete entry[key]) {
            size--;
        }
    }

    this.containsKey = function(key){
        return (key in entry);
    }

    this.containsValue = function(value){
        for(var prop in entry){
            if(entry[prop] == value){
                return true;
            }
        }
        return false;
    }
    //get all values
        this.getValues = function(){
            var values = new Array();
            for(var prop in entry){
                values.push(entry[prop]);
            }
            return values;
        }
    //get all keys
        this.getKeys = function(){
            var keys = new Array();
            for(var prop in entry){
                values.push(prop);
            }
            return keys;
        }
    this.getSize = function(){
        return size;
    }

    this.clear = function(){
        size = 0;
        entry = new Object;//???????????????????
    }
}

var hashtest = new HashTable();
hashtest.add('name','LiMing');

我想在javascript中实现哈希表,但是当我测试它时,出现这样的异常:

Uncaught ReferenceError: containsKey is not defined 在 HashTable.add (:8:3) 在:64:10

【问题讨论】:

标签: javascript hashtable


【解决方案1】:

您遇到的问题是scope 的问题。 javascript 解释器不知道您的意思是来自 HashTable 类的 containsKey

在类范围内调用函数时,请务必使用“this”引用它们。所以containsKey 应该被引用为this.containsKey(key)。这样解释器就知道你指的是类的范围而不是本地范围。

您也应该对具有类范围的变量执行此操作。所以当你写size++时,你实际上应该写this.size++entry 也一样。如果您不添加“this”,它将假定它是在该函数本身中定义的局部函数或变量。

所以你应该将你的 add() 函数重写为

this.add = function(key,value){
        if(!this.containsKey(key)){
            this.size++;
        }
        this.entry[key] = value;
    }

您为什么还要手动跟踪大小?您可以简单地将“条目”定义为数组并使用 this.entry.size

考虑到哈希图的更具体情况,我建议您在对象中简单地创建两个数组,一个用于键,一个用于值,这将大大简化您的问题,因为您可以简单地使用内置 Javascript 数组函数。两个数组都有一个数字索引,但键和值都将始终具有相同的索引,因此您可以轻松地计算它们。结果是这样的:

function HashTable() {
  this.keys = new Array();
  this.values = new Array();

  this.add = function(key, value) {

    if (this.containsKey(key)) {
      var index = this.keys.indexOf(key);
      this.values[index] = value;
    } else {
      this.keys.push(key);
      this.values.push(value);
    }
  }

  this.containsKey = function(key) {
    return this.keys.includes(key);
  }

  this.containsValue = function(value) {
    return this.values.includes(value);
  }

  this.get = function(key) {
    var index = this.keys.indexOf(key);
    return this.values[index];
  }

  this.remove = function(key) {
    if (this.containsKey(key)) {
      var index = this.keys.indexOf(key);
      this.keys.splice(index, 1);
      this.values.splice(index, 1);
    }
  }

  this.size = function() {
    return this.keys.length;
  }

  this.clear = function() {
    this.keys = new Array();
    this.values = new Array();
  }
}

// Create hashtable
var hashTable = new HashTable();

// Add some test data
hashTable.add('name', 'LiMing');
hashTable.add('location', 'At home');
hashTable.add('eyes', 'blue');

// Updates the value, doesn't add it
hashTable.add('eyes', 'brown');
console.log(hashTable.get("eyes"));

// Get the size
console.log(hashTable.size());

// Check if a value or key is in the hashtable
console.log(hashTable.containsValue("test")); // False
console.log(hashTable.containsValue("LiMing")); // True
console.log(hashTable.containsKey("name")); // True
console.log(hashTable.containsKey("age")); // False

// Get all the keys and values
console.log(hashTable.keys);
console.log(hashTable.values);

// Remove an item
hashTable.remove('eyes');
console.log(hashTable.keys);
console.log(hashTable.values);

// Clear hashtable
hashTable.clear();
console.log(hashTable.keys);
console.log(hashTable.values);

【讨论】:

  • 如果将“entry”定义为一个数组,它的key就可以是数字的类型。对不起,我的英语很差,所以如果语气很糟糕,请原谅我。
  • 没错,Javascript 不支持关联数组 (w3schools.com/js/js_arrays.asp)。但是,我只是建议您在对象中有 2 个数组,一个带有键的数组和另一个带有值的数组。
  • 您的建议对我很有价值!非常感谢!
  • 我在回答中详细说明了解决方案。您可以在 sn -p 中测试运行它。如果答案令人满意,请将问题标记为已回答。 ;)
  • 我们为什么要在这里做? Navtive map 支持任何原始、符号或敌人对象作为键,它们不是 hashmap 的理想解决方案吗?
【解决方案2】:

改用this.containsKey,因为containsKeyHashTable创建的对象内的“成员”方法,你必须用this引用它。

function HashTable(){
    var size = 0;
    var entry = new Object();
    
    this.containsValue = function(value){
        for(var prop in entry){
            if(entry[prop] == value){
                return true;
            }
        }
        return false;
    }
    
    this.add = function(key,value){
        if(!this.containsKey(key)){
            size++;
        }
        entry[key] = value;
    }

this.getValue = function(key){
    return this.containsKey(key)?entry[key]:null;
}

this.remove = function(key){
    if (this.containsKey(key) && delete entry[key]) {
        size--;
    }
}

this.containsKey = function(key){
    return (key in entry);
}


//get all values
    this.getValues = function(){
        var values = new Array();
        for(var prop in entry){
            values.push(entry[prop]);
        }
        return values;
    }
//get all keys
    this.getKeys = function(){
        var keys = new Array();
        for(var prop in entry){
            values.push(prop);
        }
        return keys;
    }
this.getSize = function(){
    return size;
}

this.clear = function(){
    size = 0;
    entry = new Object;//???????????????????
}
}

var hashtest = new HashTable(); hashtest.add('name','LiMing');
console.log(hashtest.getValues())

使用 ES6 组织代码有更好的方法:

class HashTable {
  constructor() {
    this.size = 0;
    this.entry = new Object();
  }
  
  containsValue(value) {
    for(var prop in entry){
      if(this.entry[prop] == value){
        return true;
      }
    }
    return false;
  }
  
  add(key,value) {
    if(!this.containsKey(key)){
      this.size++;
    }
    this.entry[key] = value;
  }
  
  getValue(key) {
    return this.containsKey(key) ? this.entry[key] : null;
  }
  
  remove(key) {
    if (this.containsKey(key) && delete this.entry[key]) {
      size--;
    }
  }
  
  containsKey(key) {
    return (key in this.entry);
  }
  
  //get all values
  getValues() {
    var values = new Array();
    for(var prop in this.entry){
      values.push(this.entry[prop]);
    }
    return values;
  }
  
  //get all keys
  getKeys() {
    var keys = new Array();
    for(var prop in this.entry){
      values.push(prop);
    }
    return keys;
  }
  
  getSize() {
    return this.size;
  }
  
  clear() {
    this.size = 0;
    this.entry = new Object();//???????????????????
  }
  
}


var hashtest = new HashTable(); hashtest.add('name','LiMing');
console.log(hashtest.getValues())

【讨论】:

  • 还有 this.entry 等等,并记下原生 Map 实现。
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 2020-12-30
  • 1970-01-01
  • 2016-03-25
  • 2021-04-07
  • 2011-10-14
  • 2011-09-15
相关资源
最近更新 更多