Programing

JavaScript에서 연관 배열 / 해싱을 수행하는 방법

lottogame 2020. 2. 10. 21:59
반응형

JavaScript에서 연관 배열 / 해싱을 수행하는 방법


C #에서와 같이 JavaScript를 사용하여 일부 통계를 저장해야합니다.

Dictionary<string, int> statistics;

statistics["Foo"] = 10;
statistics["Goo"] = statistics["Goo"] + 1;
statistics.Add("Zoo", 1);

이 생길인가 Hashtable또는 뭔가처럼 Dictionary<TKey, TValue>자바 스크립트?
어떻게 그런 식으로 값을 저장할 수 있습니까?


JavaScript 객체를 연관 배열로 사용하십시오 .

연관 배열 : 간단히 말해서 연관 배열은 정수 대신 정수를 인덱스로 사용합니다.

로 객체 만들기

var dictionary = {};

Javascript를 사용하면 다음 구문을 사용하여 객체에 속성을 추가 할 수 있습니다.

Object.yourProperty = value;

동일한 대체 구문은 다음과 같습니다.

Object["yourProperty"] = value;

다음 구문을 사용하여 키-값 객체 맵을 만들 수도있는 경우

var point = { x:3, y:2 };

point["x"] // returns 3
point.y // returns 2

다음과 같이 for..in 루프 구문을 사용하여 연관 배열을 반복 할 수 있습니다.

for(var key in Object.keys(dict)){
  var value = dict[key];
  /* use key/value for intended purpose */
}

var associativeArray = {};
associativeArray["one"] = "First";
associativeArray["two"] = "Second";
associativeArray["three"] = "Third";

객체 지향 언어에서 오는 경우이 기사를 확인해야합니다 .


특별한 이유가없는 한, 일반 객체 만 사용하십시오. Javascript의 객체 속성은 해시 테이블 스타일 구문을 사용하여 참조 할 수 있습니다.

var hashtable = {};
hashtable.foo = "bar";
hashtable['bar'] = "foo";

그러면 요소 foobar요소를 모두 다음과 같이 참조 할 수 있습니다.

hashtable['foo'];
hashtable['bar'];
// or
hashtable.foo;
hashtable.bar;

물론 이것은 키가 문자열이어야 함을 의미합니다. 문자열이 아닌 경우 내부적으로 문자열로 변환되므로 여전히 작동합니다 (YMMV).


모든 최신 브라우저는 자바 스크립트 객체를 지원 합니다. 객체보다지도를 더 잘 사용하는 데에는 몇 가지 이유가 있습니다.

  • 객체에는 프로토 타입이 있으므로 맵에 기본 키가 있습니다.
  • 객체의 키는 문자열이며지도의 값이 될 수 있습니다.
  • 객체의 크기를 추적해야하는 동안 맵의 크기를 쉽게 얻을 수 있습니다.

예:

var myMap = new Map();

var keyObj = {},
    keyFunc = function () {},
    keyString = "a string";

myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

myMap.size; // 3

myMap.get(keyString);    // "value associated with 'a string'"
myMap.get(keyObj);       // "value associated with keyObj"
myMap.get(keyFunc);      // "value associated with keyFunc"

다른 객체에서 참조되지 않은 키를 가비지 수집하려면 맵 대신 WeakMap을 사용하십시오 .


JS의 모든 객체는 해시 테이블처럼 동작하며 일반적으로 해시 테이블로 구현되기 때문에 그와 함께합니다.

var hashSweetHashTable = {};

C #에서 코드는 다음과 같습니다.

Dictionary<string,int> dictionary = new Dictionary<string,int>();
dictionary.add("sample1", 1);
dictionary.add("sample2", 2);

또는

var dictionary = new Dictionary<string, int> {
    {"sample1", 1},
    {"sample2", 2}
};

JavaScript로

var dictionary = {
    "sample1": 1,
    "sample2": 2
}

C #을 사전 개체는 같은 유용한 방법이 포함되어 dictionary.ContainsKey()자바 스크립트에서 우리가 사용할 수 hasOwnProperty처럼를

if (dictionary.hasOwnProperty("sample1"))
    console.log("sample1 key found and its value is"+ dictionary["sample1"]);

키가 문자열이 아닌 객체가되어야하는 경우 내 jshashtable을 사용할 수 있습니다 .


객체 키 매핑, 열거 기능 ( forEach()메소드 포함) 및 지우기 와 같은 일부 문제를 달성하기 위해 이것을 만들었습니다 .

function Hashtable() {
    this._map = new Map();
    this._indexes = new Map();
    this._keys = [];
    this._values = [];
    this.put = function(key, value) {
        var newKey = !this.containsKey(key);
        this._map.set(key, value);
        if (newKey) {
            this._indexes.set(key, this.length);
            this._keys.push(key);
            this._values.push(value);
        }
    };
    this.remove = function(key) {
        if (!this.containsKey(key))
            return;
        this._map.delete(key);
        var index = this._indexes.get(key);
        this._indexes.delete(key);
        this._keys.splice(index, 1);
        this._values.splice(index, 1);
    };
    this.indexOfKey = function(key) {
        return this._indexes.get(key);
    };
    this.indexOfValue = function(value) {
        return this._values.indexOf(value) != -1;
    };
    this.get = function(key) {
        return this._map.get(key);
    };
    this.entryAt = function(index) {
        var item = {};
        Object.defineProperty(item, "key", {
            value: this.keys[index],
            writable: false
        });
        Object.defineProperty(item, "value", {
            value: this.values[index],
            writable: false
        });
        return item;
    };
    this.clear = function() {
        var length = this.length;
        for (var i = 0; i < length; i++) {
            var key = this.keys[i];
            this._map.delete(key);
            this._indexes.delete(key);
        }
        this._keys.splice(0, length);
    };
    this.containsKey = function(key) {
        return this._map.has(key);
    };
    this.containsValue = function(value) {
        return this._values.indexOf(value) != -1;
    };
    this.forEach = function(iterator) {
        for (var i = 0; i < this.length; i++)
            iterator(this.keys[i], this.values[i], i);
    };
    Object.defineProperty(this, "length", {
        get: function() {
            return this._keys.length;
        }
    });
    Object.defineProperty(this, "keys", {
        get: function() {
            return this._keys;
        }
    });
    Object.defineProperty(this, "values", {
        get: function() {
            return this._values;
        }
    });
    Object.defineProperty(this, "entries", {
        get: function() {
            var entries = new Array(this.length);
            for (var i = 0; i < entries.length; i++)
                entries[i] = this.entryAt(i);
            return entries;
        }
    });
}


수업 서류 Hashtable

행동 양식:

  • get(key)
    지정된 키와 관련된 값을 반환합니다.
    매개 변수 :
    key : 값을 검색하는 키.

  • put(key, value)
    지정된 값을 지정된 키에 연결합니다.
    매개 변수 :
    key : 값을 연관시키는 키.
    value: 키와 연관시킬 값입니다.

  • remove(key)
    지정된 키를 값으로 제거합니다.
    매개 변수 :
    key : 제거 할 키.

  • clear()
    키와 값을 모두 제거하여 모든 해시 테이블을 지 웁니다.

  • indexOfKey(key)
    추가 순서에 따라 지정된 키의 인덱스를 반환합니다.
    매개 변수 :
    key : 색인을 얻는 키.

  • indexOfValue(value)
    추가 순서에 따라 지정된 값의 인덱스를 반환합니다.
    매개 변수 :
    value : 색인을 얻는 값.
    참고 :
    이 정보는 indexOf()배열의 메소드로 검색 되므로 객체와 toString()메소드를 비교합니다 .

  • entryAt(index)
    지정된 인덱스의 항목을 나타내는 키와 값의 두 가지 속성을 가진 객체를 반환합니다.
    파라미터 :
    index : 취득하는 엔트리의 인덱스.

  • containsKey(key)
    해시 테이블에 지정된 키가 포함되어 있는지 여부를 반환합니다.
    매개 변수 :
    key : 점검 할 키.

  • containsValue(value)
    해시 테이블에 지정된 값이 포함되어 있는지 여부를 반환합니다.
    매개 변수 :
    value : 점검 할 값.

  • forEach(iterator)
    지정된의 모든 항목을 반복합니다 iterator.
    파라미터 :
    value : 3 파라미터들에있어서 key, valueindex, index항목의 인덱스를 나타낸다.

    속성 :

  • length ( 읽기 전용 )
    해시 테이블의 항목 수를 가져옵니다.

  • keys ( 읽기 전용 )
    해시 테이블의 모든 키 배열을 가져옵니다.

  • values ( 읽기 전용 )
    해시 테이블에있는 모든 값의 배열을 가져옵니다.

  • entries ( 읽기 전용 )
    해시 테이블의 모든 항목 배열을 가져옵니다. 그것들은 같은 형식의 메소드로 표현됩니다 entryAt().


function HashTable() {
    this.length = 0;
    this.items = new Array();
    for (var i = 0; i < arguments.length; i += 2) {
        if (typeof (arguments[i + 1]) != 'undefined') {
            this.items[arguments[i]] = arguments[i + 1];
            this.length++;
        }
    }

    this.removeItem = function (in_key) {
        var tmp_previous;
        if (typeof (this.items[in_key]) != 'undefined') {
            this.length--;
            var tmp_previous = this.items[in_key];
            delete this.items[in_key];
        }

        return tmp_previous;
    }

    this.getItem = function (in_key) {
        return this.items[in_key];
    }

    this.setItem = function (in_key, in_value) {
        var tmp_previous;
        if (typeof (in_value) != 'undefined') {
            if (typeof (this.items[in_key]) == 'undefined') {
                this.length++;
            } else {
                tmp_previous = this.items[in_key];
            }

            this.items[in_key] = in_value;
        }

        return tmp_previous;
    }

    this.hasItem = function (in_key) {
        return typeof (this.items[in_key]) != 'undefined';
    }

    this.clear = function () {
        for (var i in this.items) {
            delete this.items[i];
        }

        this.length = 0;
    }
}

https://gist.github.com/alexhawkins/f6329420f40e5cafa0a4

var HashTable = function() {
  this._storage = [];
  this._count = 0;
  this._limit = 8;
}


HashTable.prototype.insert = function(key, value) {
  //create an index for our storage location by passing it through our hashing function
  var index = this.hashFunc(key, this._limit);
  //retrieve the bucket at this particular index in our storage, if one exists
  //[[ [k,v], [k,v], [k,v] ] , [ [k,v], [k,v] ]  [ [k,v] ] ]
  var bucket = this._storage[index]
    //does a bucket exist or do we get undefined when trying to retrieve said index?
  if (!bucket) {
    //create the bucket
    var bucket = [];
    //insert the bucket into our hashTable
    this._storage[index] = bucket;
  }

  var override = false;
  //now iterate through our bucket to see if there are any conflicting
  //key value pairs within our bucket. If there are any, override them.
  for (var i = 0; i < bucket.length; i++) {
    var tuple = bucket[i];
    if (tuple[0] === key) {
      //overide value stored at this key
      tuple[1] = value;
      override = true;
    }
  }

  if (!override) {
    //create a new tuple in our bucket
    //note that this could either be the new empty bucket we created above
    //or a bucket with other tupules with keys that are different than 
    //the key of the tuple we are inserting. These tupules are in the same
    //bucket because their keys all equate to the same numeric index when
    //passing through our hash function.
    bucket.push([key, value]);
    this._count++
      //now that we've added our new key/val pair to our storage
      //let's check to see if we need to resize our storage
      if (this._count > this._limit * 0.75) {
        this.resize(this._limit * 2);
      }
  }
  return this;
};


HashTable.prototype.remove = function(key) {
  var index = this.hashFunc(key, this._limit);
  var bucket = this._storage[index];
  if (!bucket) {
    return null;
  }
  //iterate over the bucket
  for (var i = 0; i < bucket.length; i++) {
    var tuple = bucket[i];
    //check to see if key is inside bucket
    if (tuple[0] === key) {
      //if it is, get rid of this tuple
      bucket.splice(i, 1);
      this._count--;
      if (this._count < this._limit * 0.25) {
        this._resize(this._limit / 2);
      }
      return tuple[1];
    }
  }
};



HashTable.prototype.retrieve = function(key) {
  var index = this.hashFunc(key, this._limit);
  var bucket = this._storage[index];

  if (!bucket) {
    return null;
  }

  for (var i = 0; i < bucket.length; i++) {
    var tuple = bucket[i];
    if (tuple[0] === key) {
      return tuple[1];
    }
  }

  return null;
};


HashTable.prototype.hashFunc = function(str, max) {
  var hash = 0;
  for (var i = 0; i < str.length; i++) {
    var letter = str[i];
    hash = (hash << 5) + letter.charCodeAt(0);
    hash = (hash & hash) % max;
  }
  return hash;
};


HashTable.prototype.resize = function(newLimit) {
  var oldStorage = this._storage;

  this._limit = newLimit;
  this._count = 0;
  this._storage = [];

  oldStorage.forEach(function(bucket) {
    if (!bucket) {
      return;
    }
    for (var i = 0; i < bucket.length; i++) {
      var tuple = bucket[i];
      this.insert(tuple[0], tuple[1]);
    }
  }.bind(this));
};


HashTable.prototype.retrieveAll = function() {
  console.log(this._storage);
  //console.log(this._limit);
};

/******************************TESTS*******************************/

var hashT = new HashTable();

hashT.insert('Alex Hawkins', '510-599-1930');
//hashT.retrieve();
//[ , , , [ [ 'Alex Hawkins', '510-599-1930' ] ] ]
hashT.insert('Boo Radley', '520-589-1970');
//hashT.retrieve();
//[ , [ [ 'Boo Radley', '520-589-1970' ] ], , [ [ 'Alex Hawkins', '510-599-1930' ] ] ]
hashT.insert('Vance Carter', '120-589-1970').insert('Rick Mires', '520-589-1970').insert('Tom Bradey', '520-589-1970').insert('Biff Tanin', '520-589-1970');
//hashT.retrieveAll();
/* 
[ ,
  [ [ 'Boo Radley', '520-589-1970' ],
    [ 'Tom Bradey', '520-589-1970' ] ],
  ,
  [ [ 'Alex Hawkins', '510-599-1930' ],
    [ 'Rick Mires', '520-589-1970' ] ],
  ,
  ,
  [ [ 'Biff Tanin', '520-589-1970' ] ] ]
*/

//overide example (Phone Number Change)
//
hashT.insert('Rick Mires', '650-589-1970').insert('Tom Bradey', '818-589-1970').insert('Biff Tanin', '987-589-1970');
//hashT.retrieveAll();

/* 
[ ,
  [ [ 'Boo Radley', '520-589-1970' ],
    [ 'Tom Bradey', '818-589-1970' ] ],
  ,
  [ [ 'Alex Hawkins', '510-599-1930' ],
    [ 'Rick Mires', '650-589-1970' ] ],
  ,
  ,
  [ [ 'Biff Tanin', '987-589-1970' ] ] ]

*/

hashT.remove('Rick Mires');
hashT.remove('Tom Bradey');
//hashT.retrieveAll();

/* 
[ ,
  [ [ 'Boo Radley', '520-589-1970' ] ],
  ,
  [ [ 'Alex Hawkins', '510-599-1930' ] ],
  ,
  ,
  [ [ 'Biff Tanin', '987-589-1970' ] ] ]


*/

hashT.insert('Dick Mires', '650-589-1970').insert('Lam James', '818-589-1970').insert('Ricky Ticky Tavi', '987-589-1970');
hashT.retrieveAll();


/* NOTICE HOW HASH TABLE HAS NOW DOUBLED IN SIZE UPON REACHING 75% CAPACITY ie 6/8. It is now size 16.
 [,
  ,
  [ [ 'Vance Carter', '120-589-1970' ] ],
  [ [ 'Alex Hawkins', '510-599-1930' ],
    [ 'Dick Mires', '650-589-1970' ],
    [ 'Lam James', '818-589-1970' ] ],
  ,
  ,
  ,
  ,
  ,
  [ [ 'Boo Radley', '520-589-1970' ],
    [ 'Ricky Ticky Tavi', '987-589-1970' ] ],
  ,
  ,
  ,
  ,
  [ [ 'Biff Tanin', '987-589-1970' ] ] ]




*/
console.log(hashT.retrieve('Lam James'));  //818-589-1970
console.log(hashT.retrieve('Dick Mires')); //650-589-1970
console.log(hashT.retrieve('Ricky Ticky Tavi')); //987-589-1970
console.log(hashT.retrieve('Alex Hawkins')); //510-599-1930
console.log(hashT.retrieve('Lebron James')); //null

다음과 같은 방법으로 만들 수 있습니다.

var dictionary = { Name:"Some Programmer", Age:24, Job:"Writing Programs"  };

//Iterate Over using keys
for (var key in dictionary) {
  console.log("Key: " + key + " , " + "Value: "+ dictionary[key]);
}

//access a key using object notation:
console.log("Her Name is: " + dictionary.Name)

참고 URL : https://stackoverflow.com/questions/1208222/how-to-do-associative-array-hashing-in-javascript



반응형