Check for duplicates in an array - javascript

I have a function that will check a serialized form data if there are duplicates values in it.
s = $('#multiselectForm').serialize();
var x = [];
var y = [];
x = s.split("&");
for (var i = x.length - 1; i >= 0; i--) {
y.push(x[i].split("="));
};
var c = 0;
var e = 0;
for (var i = y.length - 1; i >= 0; i--) {
if (y[i][1] == y[c][1]) {
e++;
$('.duplicateAlert').show();
} else {
$('.duplicateAlert').hide();
};
c++;
};
Basically, what it does is split the string produced by the serialize() function and push the data into arrays.
The array I'm trying to parse looks like this:
Array [
Array [
0: 'my_field1',
1: 'val1'
],
Array [
0: 'my_field2'
1: 'val2'
],
Array [
0: 'my_field3'
1: 'val1'
]
]
Are there any better ways to do the same task? Maybe even shorter?

Create an empty array to hold the matches
Loop through the array. On each iteration...
Loop through the matches array and check if an item with the same value exists. If it does, set the matched flag.
Check if the matched flag has been set
if so, alert the user
if not add the item to matches.
var array = [
[ 'my_field1', 'val1' ],
[ 'my_field2', 'val2' ],
[ 'my_field3', 'val1' ],
[ 'my_field4', 'val2' ],
[ 'my_field5', 'val3' ]
], matches = [], match = false;
for(var i = 0, j = array.length; i < j; i++) {
match = false;
for(var k = 0, l = matches.length; k < l; k++) {
if(matches[k][1] == array[i][1]) {
match = true;
}
}
if(match) alert('Duplicate!');
else matches.push(array[i]);
}

If you have serialised data in the typical format like:
var data = 'foo=foo&bar=bar%26bar&blah=foo';
then you can check it for duplicates by getting the values between = and & and looking for dupes:
var seen = {};
var hasDupes = (data.match(/=[^&]+/g) || []).some(function(v){
return v in seen || (seen[v] = true) && false;
});
console.log(hasDupes); // true
The idea behind:
data.match(/=[^&]+/g) || []
is that match can return null if no matches are found, so if that happens the expression returns an empty array and the following call to some is called on the empty array (and returns false) rather than null, and hence doesn't throw the error that it would otherwise.
However, I still think it would be more efficient to check the form control values directly before serialising, rather than serialising the form then checking the result.
You can do that with a function like:
function checkDupValues(form) {
var value,
seen = {},
controls = form.elements;
for (var i=0, iLen=controls.length; i<iLen; i++) {
// Might want to check type of control here and ignore buttons, etc.
value = controls[i].value;
// Ignore empty controls?
if (value != '' && value in seen) {
// have a duplicate value that is not ''
alert('have dupes');
} else {
seen[value] = true;
}
}
}

Try this although its not much shorter:
var array = [
[
'my_field1',
'val1'
],
[
'my_field2',
'val2'
],
[
'my_field3',
'val1'
]
]
var originals = [];
var duplicates = [];
for (a in array) {
if (originals.indexOf(array[a][1] == -1)) {
originals.push(array[a][1])
} else {
duplicates.push(array[a])
}
}
alert('duplicates: ' + duplicates.join(', '));

Related

Javascript - Adding multiple values to keys

I am trying to find the places of each letter in a sentence by using "dictionaries". The problem is I want to find all the places that each letter is and not only the last one. I am very new to JavaScript and couldn't figure out the way to do it.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ )
if (!stringArgument[i] in dict){
dict[stringArgument[i]] = [];
}else{
dict[stringArgument[i]] = [i+1]
}
return dict
}
var a = letters('Lost time is never found again.');
console.log(a);
naturally gives this output:
{ L: [ 1 ], o: [ 17 ], s: [ 10 ], t: [ 5 ]...
but it should give this:
{ L: [ 1 ], o: [ 2, 17 ], s: [ 3, 10 ], t: [ 4, 5 ]...
Also each letter is saved to the dictionary at the same order they appear in the sentence, how can I order the letters alphabetically?
What you need is a function that gets the positions of a character in a given string.
Try this:
function findAllPositions(char, content) {
var result = [];
let index = content.indexOf(char);
while(index !== -1) {
result.push(index);
index = content.indexOf(char, index + 1);
}
return result;
}
findAllPositions('o', 'Lost time is never found again.'); // Result =  [1, 20]
Using this we can update the letter function as follows:
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (const char of stringArgument) {
dict[char] = findAllPositions(char, stringArgument)
}
return dict;
}
letters('is again.')
/*
{
"i": [0, 5],
"s": [1],
"a": [2, 4],
"g": [3],
"n": [6],
".": [7]
}
*/
You need to have
parantheses for the check
if (!(stringArgument[i] in dict)) {
create an array if the above is true
push the postion to the array
For getting a sorted output, you could take the entries of the object, apply a sorting by taking the key and show the result in order.
Object have an insertation oder for not positive 32 bit numbers (like indixes) or symbols. The index like numbers are sorted by value and appears first in the object.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
if (!(stringArgument[i] in dict)) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters('Lost time is never found again.');
Object
.entries(a)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([key, positions]) => console.log(key, ...positions));
console.log(a);
First, for any item, if it is not in an empty array:
var notInDict = !(stringArgument[i] in dict);
If not in dict, then initialize an empty array and push the item in it using
dict[stringArgument[i]].push(i + 1);
Try this.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, "");
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
var notInDict = !(stringArgument[i] in dict);
if (notInDict) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters("Lost time is never found again.");
console.log(a);
you are assigning a new array at each iteration
dict[stringArgument[i]] = [i+1]
what you need to do is push the new position to existing array.
dict[stringArgument[i]].push(i+1)
also, remove the else block
function letters(stringArgument) {
stringArgument = stringArgument.toLowerCase().replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ ){
if (!dict.hasOwnProperty(stringArgument[i])){
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i+1);
}
//sorting
var letters = Object.keys(dict); //returns a array
letters.sort();
var sortedDic = {};
for(var i in letters) {
sortedDic[letters[i]] = dict[letters[i]];
}
return sortedDic;
}
var a = letters('Lost time is never found again.');
console.log(a);
for the first part you can also do that:
let sentence = 'Lost time is never found again.'
let tabLetters = [...sentence.replace(/ /g,'')].reduce((a,c,i)=>
{
if (!a[c]) a[c] = [i+1]
else a[c].push(i+1)
return a
},{})
document.write(JSON.stringify(tabLetters))

How can I check if a value exists in an array with multiple objects - javascript?

So my array looks like this:
let array = [
{"object1":1},
{"object2":2},
{"object3":3}
];
What I want to do is to check, for example, whether or not "object1" exists. The way I would prefer is pure Javascript.
I am doing this for large chunks of data and so my code needs to be something like this:
if ("opensprint1" in array){
console.log("yes, this is in the array");
} else {
console.log("no, this is not in the array");
};
NOTE: I have tried to use the (in) function in JS and the (hasOwnProperty) and neither has worked.
Any ideas?
if ("opensprint1" in array){
That check for the array keys, so it would work with:
if ("0" in array){
But actually you want to check if some of the array elements got that key:
if(array.some( el => "opensprint1" in el))
You're trying to filter an array of objects. You can pass a custom function into Array.prototype.filter, defining a custom search function. It looks like you want to search based on the existence of keys. If anything is returned, that key exists in the object array.
let array = [{
"object1": 1
},
{
"object2": 2
},
{
"object3": 3
}
];
const filterByKey = (arr, keyName) =>
array.filter(obj => Object.keys(obj).includes(keyName)).length > 0;
console.log(filterByKey(array, 'object1'));
console.log(filterByKey(array, 'object5'));
That is roughly equivalent to:
let array = [{
"object1": 1
},
{
"object2": 2
},
{
"object3": 3
}
];
const filterByKey = (arr, keyName) => {
// iterate each item in the array
for (let i = 0; i < arr.length; i++) {
const objectKeys = Object.keys(arr[i]);
// take the keys of the object
for (let j = 0; j < objectKeys.length; j++) {
// see if any key matches our expected
if(objectKeys[i] === keyName)
return true
}
}
// none did
return false;
}
console.log(filterByKey(array, 'object1'));
console.log(filterByKey(array, 'object5'));
This might help you
let array = [
{"object1":1},
{"object2":2},
{"object3":3}
];
let targetkey = "opensprint1";
let exists = -1;
for(let i = 0; i < array.length; i++) {
let objKeys = Object.keys(array[i]);
exists = objKeys.indexOf(targetkey);
if (exists >= 0) {
break;
}
}
if (exists >= 0) {
console.log("yes, this is in the array");
} else {
console.log("no, this is not in the array");
}
let array = [
{ "object1": 1 },
{ "object2": 2 },
{ "object3": 3 }
];
let checkKey = (key) => {
var found = false;
array.forEach((obj) => {
if (!(obj[key] === undefined)) {
found = true;
array.length = 0;
}
});
return found;
}
console.log(checkKey("object2"));
In this case, I think one of the most efficient way is to do a for and break like:
let array = [
{"object1":1},
{"object2":2},
{"object3":3}
];
exist = false;
for(let i = 0; i<array.length; i++){
if("object1" in array[i]){
exist = true;//<-- We just know the answer we want
break;//<-- then stop the loop
}
}
console.log(exist);
When iteration finds a true case, stops the iteration. We can't perform a break in .map, .filter etc. So the number of iterations are the less possible. I think this is also the case of .some()

how to count children in object in javascript?

I have a json array ..I want to refactor the json object ..but I am not able to make as expected output .I want to search all item or object and insert the children of parent ..I try like that
https://jsfiddle.net/nk6v0y36/1/
var new_Arry = [];
for (var i = 0; i < arry.length; i++) {
var obj = {};
var childeren = [];
obj.con_id = arry[i].con_id;
obj.children = [{
con_to: arry[i].con_to
}];
new_Arry.push(obj)
}
console.log(new_Arry)
Expected output:
[{
"con_id": 11,
"children": [{
"con_to": 12
}]
}, {
"con_id": 12,
"children": [{
"con_to": 13
}, {
"con_to": 14
}]
}, {
"con_id": 13,
"children": []
}, {
"con_id": 14,
"children": [{
"con_to": 15
}]
}, {
"con_id": 15,
"children": [{
"con_to": 16
}]
}, {
"con_id": 16,
"children": []
}]
After answer
https://jsfiddle.net/nk6v0y36/7/
Answer not working..
As thisOneGuy said, you are not checking if a con_id already exists in the new array, so for each element in the old array you are creating a corresponding new one. Your expected output though shows you want to merge these multiple con_id values into a single object.
You are also creating objects with con_to properties in the children arrays even when there is no such property, which again your expected output suggests you do not way.
One way to fix this would be:
var new_Arry = [];
var new_Hash = [];
for (var i = 0; i < arry.length; i++) {
if (new_Hash[arry[i].con_id] === undefined ) {
var obj = {
con_id: arry[i].con_id,
children: []
};
if( arry[i].con_to !== undefined ) {
obj.children.push({ con_to: arry[i].con_to });
}
new_Hash[obj.con_id] = new_Arry.push(obj) - 1;
} else if( arry[i].con_to !== undefined ) {
new_Arry[new_Hash[arry[i].con_id]].children.push({ con_to: arry[i].con_to });
}
}
console.log(new_Arry);
The key here is the new_Hash array, which uses the con_id value as its key, and stores the respective index in the new_Arry as its value.
So for each con_id in arry it first checks the new_Hash to see if there is an entry for it. If not then there is no entry in new_Arry, so it creates a new one.
Firstly the basic object, with con_id and a children array is created. It then checks whether there is a con_to property in arry, and only if there is does it add one as an object to the children array.
This object is then added to new_Arry and new_Hash updated so that an element for con_id references the new new_Arry index. As the .push() method returns extends an array and returns the new array length, the new index will always be this value minus one.
However if an entry for con_id was found in new_Hash then all you need to do it add the con_to value to the existing children array. Whilst presumably if there are multiple con_id entries in arry they must contain a con_to value, it also checks this just to be safe. The index number for the new_Arry as returned by new_Hash[arry[i].cond_id].
Incidentally, the reason for explicitly checking for undefined rather than seeing if value equates to true or false to check for its existence is a con_id or con_to value of 0 would be treated as false and skipped.
Like this -
var new_Arry = [];
for (var i = 0; i < arry.length; i++) {
var obj = {};
var childeren = [];
obj.con_id = arry[i].con_id;
var child = [];
var childrenObj = {};
childrenObj.con_to = arry[i].con_to;
child.push(childrenObj);
obj.children = child;
new_Arry.push(obj)
}
https://jsfiddle.net/nk6v0y36/3/
Here is the correct answer with the correct output : https://jsfiddle.net/nk6v0y36/4/
Basically you need to loop through your array to check if the con_id exists in that array, if it does, just add to children, if it doesnt add a new object.
var new_Arry = [];
for (var i = 0; i < arry.length; i++) {
var obj = {};
var childeren = [];
if (new_Arry.length > 0) {
console.log('start')
console.log(new_Arry.length);
var thisBool = false;
for (var j = 0; j <= new_Arry.length; j++) {
console.log('inside')
if (new_Arry[j]) {
if (new_Arry[j].con_id === arry[i].con_id) {
console.log('has children')
new_Arry[j].children[new_Arry[j].children.length] = {
con_to: arry[i].con_to
}
} else {
thisBool = true;
}
}
}
if(thisBool){
obj.con_id = arry[i].con_id;
obj.children = [{
con_to: arry[i].con_to
}];
new_Arry.push(obj)
}
} else {
console.log('no children')
obj.con_id = arry[i].con_id;
obj.children = [{
con_to: arry[i].con_to
}];
new_Arry.push(obj)
}
}
Check the output in the console log to see it's correct :)

Trying to loop through arrays containing arrays containing objects, to match data

I'm tryign to write code that will loop through an array "productsArray" and match it against my productPropertyArray to pull matching information.
however productsArray is an array in an array that contains an object with the data. My Question is how can I loop through both arrays and then return the matching data.
Current function:
var pList = productsArray
if (productPropertyArray.length === 0 || productsArray.length === 0) return [];
for (var i = 0; i < pList.length; i++) {
for (var j = 0; j < pList[i].length; j++) {
if (pList[i][j] === productPropertyArray) {
return productPropertyArray;
} else {
continue;
}
}
}
return [];
};
example of pList:
productsArray = [
[{"sku" : "131674"},
{"sku" : "84172"}],
[{"productID" : "1234"}
,{"productID" : "12345"}],
[{"test": 1},{"test": 1}],
[{"test": 1},{"sellAlone": false,"test": 1}],
[{"test": 1}],
[{"sellAlone": false,"test": 1}]
];
example of productPropertyArray: (its an argument thats replaced by the following)
productSKUArray = [
"00544MF24F575",
"131674",
"84172"
];
productPropertyArray is just an argument in the function which is replaced by productSKUArray The setup goes like this: function(productProperty, productPropertyArray, productsArray) {
productProperty is just a string that contains sku or productID
any ideas are appreciated. thanks.
Check this out:
http://jsfiddle.net/v9d7bjms/2/
function find() {
var productsArray = [
[{"sku" : "131674"},
{"sku" : "84172"}],
[{"productID" : "1234"}
,{"productID" : "12345"}],
[{"test": 1},{"test": 1}],
[{"test": 1},{"sellAlone": false,"test": 1}],
[{"test": "00544MF24F575"}],
[{"sellAlone": false,"test": 1}]
],
pList = productsArray,
productSKUArray = [
"00544MF24F575",
"131674",
"84172"
];
// All arrays matching your productsSKUArray
var findings = productsArray.filter(function (productProperty) {
// .some returns true after finding first matching element (and breaks the loop)
return productProperty.some(function (obj) {
var keys = Object.keys(obj);
// We need to get all the "values" from object so we interate over
// the keys and check if any value matches something from productSKUArray
return keys.some(function (key) {
// Check if value exists in productsSKUArray
return productSKUArray.indexOf(obj[key]) > -1;
});
});
});
return findings;
}
console.log(find());
.filter will return all arrays containing objects with values from productSKUArray.
See Array.prototype.filter, Array.prototype.some and Array.prototype.indexOf for method reference.
The inner if needs to refer to pList[i][j].
This will output [{sku: "131674"}, {sku: "84172"}].
var matchingData = [];
for(var productProperties in productsArray){
var pp = productsArray[productProperties];
for(var property in pp) {
var p = pp[property];
for(var propertyName in p){
var propertyValue = p[propertyName];
for(var i in productSKUArray){
if(propertyValue == productSKUArray[i]){
matchingData.push(p);
break;
}
}
}
}
}
but this is just the brute force solution.

Can anyone recommend a good Hashtable implementation in Javascript? [duplicate]

I need to store some statistics using JavaScript in a way like I'd do it in C#:
Dictionary<string, int> statistics;
statistics["Foo"] = 10;
statistics["Goo"] = statistics["Goo"] + 1;
statistics.Add("Zoo", 1);
Is there an Hashtable or something like Dictionary<TKey, TValue> in JavaScript?
How could I store values in such a way?
Use JavaScript objects as associative arrays.
Associative Array: In simple words associative arrays use Strings instead of Integer numbers as index.
Create an object with
var dictionary = {};
JavaScript allows you to add properties to objects by using the following syntax:
Object.yourProperty = value;
An alternate syntax for the same is:
Object["yourProperty"] = value;
If you can, also create key-to-value object maps with the following syntax:
var point = { x:3, y:2 };
point["x"] // returns 3
point.y // returns 2
You can iterate through an associative array using the for..in loop construct as follows
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";
If you are coming from an object-oriented language you should check this article.
All modern browsers support a JavaScript Map object. There are a couple of reasons that make using a Map better than Object:
An Object has a prototype, so there are default keys in the map.
The keys of an Object are Strings, where they can be any value for a Map.
You can get the size of a Map easily while you have to keep track of size for an Object.
Example:
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"
If you want keys that are not referenced from other objects to be garbage collected, consider using a WeakMap instead of a Map.
Unless you have a specific reason not to, just use a normal object. Object properties in JavaScript can be referenced using hashtable-style syntax:
var hashtable = {};
hashtable.foo = "bar";
hashtable['bar'] = "foo";
Both foo and bar elements can now then be referenced as:
hashtable['foo'];
hashtable['bar'];
// Or
hashtable.foo;
hashtable.bar;
Of course this does mean your keys have to be strings. If they're not strings they are converted internally to strings, so it may still work. Your mileage may vary.
Since every object in JavaScript behaves like - and is generally implemented as - a hashtable, I just go with that...
var hashSweetHashTable = {};
In C# the code looks like:
Dictionary<string,int> dictionary = new Dictionary<string,int>();
dictionary.add("sample1", 1);
dictionary.add("sample2", 2);
or
var dictionary = new Dictionary<string, int> {
{"sample1", 1},
{"sample2", 2}
};
In JavaScript:
var dictionary = {
"sample1": 1,
"sample2": 2
}
A C# dictionary object contains useful methods, like dictionary.ContainsKey()
In JavaScript, we could use the hasOwnProperty like:
if (dictionary.hasOwnProperty("sample1"))
console.log("sample1 key found and its value is"+ dictionary["sample1"]);
If you require your keys to be any object rather than just strings, then you could use my jshashtable.
Note:
Several years ago, I had implemented the following hashtable, which has had some features that were missing to the Map class. However, that's no longer the case — now, it's possible to iterate over the entries of a Map, get an array of its keys or values or both (these operations are implemented copying to a newly allocated array, though — that's a waste of memory and its time complexity will always be as slow as O(n)), remove specific items given their key, and clear the whole map.
Therefore, my hashtable implementation is only useful for compatibility purposes, in which case it'd be a saner approach to write a proper polyfill based on this.
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;
}
});
}
Documentation of the class Hashtable
Methods:
get(key)
Returns the value associated to the specified key.
Parameters:
key: The key from which to retrieve the value.
put(key, value)
Associates the specified value to the specified key.
Parameters:
key: The key to which associate the value.
value: The value to associate to the key.
remove(key)
Removes the specified key, together with the value associated to it.
Parameters:
key: The key to remove.
clear()
Clears the whole hashtable, by removing all its entries.
indexOfKey(key)
Returns the index of the specified key, according to the order entries have been added.
Parameters:
key: The key of which to get the index.
indexOfValue(value)
Returns the index of the specified value, according to the order entries have been added.
Parameters:
value: The value of which to get the index.
Remarks:
Values are compared by identity.
entryAt(index)
Returns an object with a key and a value properties, representing the entry at the specified index.
Parameters:
index: The index of the entry to get.
containsKey(key)
Returns whether the hashtable contains the specified key.
Parameters:
key: The key to look for.
containsValue(value)
Returns whether the hashtable contains the specified value.
Parameters:
value: The value to look for.
forEach(iterator)
Iterates through all the entries in the hashtable, calling specified iterator.
Parameters:
iterator: A method with three parameters, key, value and index, where index represents the index of the entry according to the order it's been added.
Properties:
length (Read-only)
Gets the count of the entries in the hashtable.
keys (Read-only)
Gets an array of all the keys in the hashtable.
values (Read-only)
Gets an array of all the values in the hashtable.
entries (Read-only)
Gets an array of all the entries in the hashtable. They're represented the same as the method 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) {
// Override 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' ] ] ]
*/
// Override 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 THE HASH TABLE HAS NOW DOUBLED IN SIZE UPON REACHING 75% CAPACITY, i.e. 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
You can create one using like the following:
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)

Categories