How can method getMetricByStatString (statString) be done on O(1)? - javascript

// CatalogAPI is a object that contains two methods for data retrieving
var CatalogAPI = {
// Returns a promise. When it resolves, it returns an array of arrays, containing category data.
getCategories: function () {
return new Promise(function (resolve) {
var categoriesData = [[1, 'device', 'http', 'HTTP'],
[2, 'device', 'dns', 'DNS'],
[3, 'application', 'ldap', 'LDAP'],
[4, 'application', 'mongo', 'MongoDB']];
resolve(categoriesData);
});
},
// Returns a promise. When it resolves, it returns an array of arrays, containing metric data.
getMetrics: function () {
return new Promise(function (resolve) {
var metricsData = [[1, 1, 'req', 'Requests'],
[2, 1, 'rsp', 'Responses'],
[3, 1, 'tprocess', 'Server Processing Time'],
[4, 2, 'req', 'Requests'],
[5, 2, 'rsp', 'Responses'],
[6, 2, 'trunc', 'Truncated Responses'],
[7, 3, 'plain', 'Plain Text Messages'],
[8, 3, 'sasl', 'SASL Messages'],
[9, 3, 'error', 'Errors'],
[10, 4, 'req', 'Requests'],
[11, 4, 'rsp', 'Responses'],
[12, 4, 'tprocess', 'Server Processing Time']];
resolve(metricsData);
});
}
};
/* custom constructor that creates a Category object
parameters: categoryData, an array containing category data in the following order:
[0] = ID, [1] = objectType, [2] = statName, [3] = displayName
*/
function Category(categoryData) {
this.ID = categoryData[0];
this.objectType = categoryData[1];
this.statName = categoryData[2];
this.displayName = categoryData[3];
};
/* custom constructor that creates a Metric object
parameters: metricData, an array containing metric data in the following order:
[0] = ID, [1] = categoryID, [2] = fieldName, [3] = displayName
*/
function Metric(metricData) {
this.ID = metricData[0];
this.categoryID = metricData[1];
this.fieldName = metricData[2];
this.displayName = metricData[3];
};
/* custom contructor that creates a Catalog object
attributes: initilized --> indicates if the object Catalog has been initialized already, set to false when first created
categories --> contains the categories data downloaded thru the CatalogAPI, set to empty when first created
metrics --> contains the metrics data downloaded thru the CatalogAPI, set to empty when first created
methods: getCategoryByID(ID)
getCategoryByStatString(statString)
getMetricByID(ID)
getMetricByStatString(statString)
initialize()
*/
function Catalog() {
this.initialized = false;
this.categories = [];
this.metrics = [];
/* searches the categories to check if a category matches a given ID,
if found, it returns a Category object with the found category's attributes
else, it returns a Category object with null attributes
*/
this.getCategoryByID = function (ID) {
var categoryObj = new Category([null, null, null, null]);
for (var i = 0; i < this.categories.length; i++) {
if (this.categories[i][0] === ID) {
categoryObj = new Category(this.categories[i]);
}
}
return categoryObj;
};
/* searches the categories to check if a category matches a given statString,
if found, it returns a Category object with the found category's attributes
else, it returns a Category object with null attributes
*/
this.getCategoryByStatString = function (statString) {
var categoryObj = new Category([null, null, null, null]);
var splittedStatString = statString.split(".");
for (var i = 0; i < this.categories.length; i++) {
if ((this.categories[i][1] === splittedStatString[1]) &&
(this.categories[i][2] === splittedStatString[2])) {
categoryObj = new Category(this.categories[i]);
}
}
return categoryObj;
};
/* searches the metrics to check if a metric matches a given ID,
if found, it returns a Metric object with the found metric's attributes
else, it returns a Metric object with null attributes
*/
this.getMetricByID = function (ID) {
var metricObj = new Metric([null, null, null, null]);
for (var i = 0; i < this.metrics.length; i++) {
if (this.metrics[i][0] === ID) {
metricObj = new Metric(this.metrics[i]);
}
}
return metricObj;
};
/* searches the metrics to check if a metric matches a given statString,
if found, it returns a Metric object with the found metric's attributes
else, it returns a Metric object with null attributes
*/
this.getMetricByStatString = function (statString) {
var metricObj = new Metric([null, null, null, null]);
// method getCategoryByStatString is called to identify the cateogry that the metric belongs to
var splittedStatString = statString.split(":");
var categoryObj = this.getCategoryByStatString(splittedStatString[0]);
// once the metric's cateogry is known, the metric is found by searching for categoryID and fieldName
for (var i = ((categoryObj.ID - 1) * 3) ; i < (categoryObj.ID * 3) ; i++) {
if (this.metrics[i][2] === splittedStatString[1]) {
metricObj = new Metric(this.metrics[i]);
}
}
return metricObj;
};
/* it returns a promise when the Catalog is ready to use,
if the catalog data was already downloaded, it does not downloads the data again
*/
this.initialize = function () {
// reference to catalog class, so that refering to catalog inside functions is easier
var catalogReference = this;
/* if initialized === true, then do not download catalog data,
just return promise acknowloging that the Catalog is ready to be use */
if (catalogReference.initialized) {
return new Promise(function (resolve) {
resolve();
});
}
/* if initialized === false, then download the catalog
data by calling the CatalogAPI methods */
else {
var categoriesData = CatalogAPI.getCategories();
var metricsData = CatalogAPI.getMetrics();
var dataReady = Promise.all([categoriesData, metricsData]).then(function (catalogData) {
catalogReference.categories = catalogData[0];
catalogReference.metrics = catalogData[1];
});
catalogReference.initialized = true;
return dataReady;
}
};
};
var c = new Catalog();
c.initialize().then(function () {
var category1, category2, metric1, metric2;
// Test category lookups
category1 = c.getCategoryByID(1);
category2 = c.getCategoryByStatString('extrahop.device.http');
if (category1.ID === category2.ID) {
console.log(category1.displayName + ' lookups match!');
}
// Test metric lookups
metric1 = c.getMetricByID(12);
metric2 = c.getMetricByStatString('extrahop.application.mongo:tprocess');
if (metric1.ID === metric2.ID) {
console.log(metric1.displayName + ' lookups match!');
}
});
The method getMetricBySatString(statString) has a parameter that is a string that contains 2 attributes from the categoriesData array and one from metricData, and it's supposed to be accomplished in the O(1), any ideas on how to accomplish that?
Thanks.

Related

How can we update or refresh/renew filtered array?-javascript

updating filtered array every time original array adds/inputs a new element
so every time I input a new element in the original array, then the filtered array gets refreshed and considers if the new element is in its condition
What about this, i am overriding the push method of the original array, so that when an new element is added, another method is going to get called to refresh the filtered array:
var originalArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var filteredArray = [...originalArray];
var filters = [];
// FUNCION THAT RECEIVES AN ARRAY AND OVERRIDES THE PUSH METHOD
//SO THAT IT CAN EXECUTE A FUNCION AFTER PUSHING THE NEW ELEMENT
var AddEventToArrayPush = (arr, callback) => {
arr.push = function(e) {
Array.prototype.push.call(arr, e);
callback(arr);
};
};
var ResetFilters = () => {
filters = [];
filteredArray = [...originalArray];
}
var AddFilter = (filter) => {
filters.push(filter);
}
var ApplyFilters = () => {
filteredArray = [...originalArray];
for (const filter of filters) {
filteredArray = filteredArray.filter(filter);
}
}
//CALLING THE FUNCTION TO OVERRIDE PUSH METHOD FOR THE ORIGINAL ARRAY
AddEventToArrayPush(originalArray, ApplyFilters)
// SOME FILTERS
const IS_EVEN_NUMBER = (number) => { return number % 2 == 0 };
const IS_GREATER_THEN_5 = (number) => { return number > 5 };
console.log("Initial filtered array:");
console.log(filteredArray.toString());
console.log("\r\nFiltering even numbers greater than 5");
AddFilter(IS_EVEN_NUMBER);
AddFilter(IS_GREATER_THEN_5);
ApplyFilters();
console.log("\r\nFiltered array after applying filters:");
console.log(filteredArray.toString());
originalArray.push(20);
console.log("\r\nFiltered array after pushing new element into original array:");
console.log(filteredArray.toString());

How to iterate over a Set or Map in reverse order in javascript?

I'm looking for a a way to iterate over a Set or Map in reverse order.
Consider this simple example in regular order:
var mySet = new Set([1,2,3,4,5]);
for(let myNum of mySet) {
console.log(myNum); // output: 1, 2, 3, 4, 5 in sepearte lines
}
The iterator given from Set.prototype.values() or Set.prototype.entries() are also from start to beginning.
What would be the solution to iterate the Set (or Map) in the reverse order?
There is no way to obtain a reversed iterator on Maps or Sets, as I have found out while trying to get the last item added to a Set. So the only way really is to use an intermediate Array and reverse it, like this:
var mySet = new Set([1,2,3,4,5]);
for (let myNum of Array.from(mySet).reverse()) {
console.log(myNum);
}
Or you can use this alternate doubly linked Set implementation:
class LinkedSetLink {
constructor(value) {
this.value = value;
this.prev = this;
this.next = this;
}
insertBefore(item) {
const prev = item.prev = this.prev;
const next = item.next = this;
next.prev = item;
prev.next = item;
}
remove() {
const prev = this.prev;
const next = this.next;
next.prev = prev;
prev.next = next;
}
}
class LinkedSet {
constructor(iterable) {
this._map = new Map();
this._pivot = new LinkedSetLink(/* undefined */);
if (iterable) {
this._addAll(iterable);
}
}
_addAll(iterable) {
for (const item of iterable) {
this.add(item);
}
}
has(item) {
return this._map.has(item);
}
add(item) {
if (!this._map.has(item)) {
const link = new LinkedSetLink(item);
this._pivot.insertBefore(link);
this._map.set(item, link);
}
}
delete(item) {
const link = this._map.get(item);
if (link) {
this._map.delete(item);
link.remove();
}
}
clear() {
this._map.clear();
this._pivot.next = this._pivot.prev = this._pivot;
}
get size() {
return this._map.size;
}
values() {
return this._map.keys();
}
keys() {
return this.values();
}
[Symbol.iterator]() {
return this.values();
}
*entries() {
for (const key of this.values()) {
yield [key, key];
}
}
*reversedItems() {
let link = this._pivot.prev;
while (link !== this._pivot) {
yield link.value;
link = link.prev;
}
}
first() {
return this._pivot.next.value;
}
last() {
return this._pivot.prev.value;
}
}
const myset = new LinkedSet([1,2,3,4,5]);
for (let item of myset.reversedItems()) {
console.log(item);
}
You can also consider adding a custom iterator to your Set or Map:
const mySet = new Set([1, 2, 3, 4, 5]);
const myMap = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
[4, 'four'],
[5, 'five']
]);
const customIterator = function () {
// get the values from the Set or Map to iterate over
// you could also use .entries() instead of .values()
// to get the key/value pairs in case of the Map
const values = Array.from(this.values());
// start at the end of the array
let index = values.length;
// the custom iterator function returns an object with a next() function
// this will be called repeatedly by for...of
return {
next: function () {
// the next() function returns an object with a done property
// to indicate when iteration is completed, and a value property
// holding the current value
return {
done: index === 0,
// `--` in front, so it decreases 'in place'
value: values[--index]
};
}
}
};
// add the customIterator to the [Symbol.iterator] property
mySet[Symbol.iterator] = customIterator;
myMap[Symbol.iterator] = customIterator;
// using for...of on the Set
for(const item of mySet) {
console.log('set:', item);
// you can also break on some condition e.g.
// if(item === 3){ break; }
}
// using for...of on the Map
for(const item of myMap) {
console.log('map:', item);
}
Additional info can be found on MDN:
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Set/##iterator
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map/##iterator
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator
var mySet = new Set([1,2,3,4,5]);
var reverse = [...mySet].reverse();
for(let myNum of reverse){
console.log(myNum);
}
You could also use reduceRight() for the loop and ignore the returned callback value.
Depending on your loop task, reduceRight() can be up to 20% faster than reverse()..
For larger datasets (>1000 items) reverse() + for(){} loop seems to be faster..
Bench:
https://jsben.ch/8vWhD
let mySet = new Set([1, 2, 3, 4, 5]);
let myMap = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
[4, 'four'],
[5, 'five']
]);
console.log('⎯⎯⎯⎯⎯ Set ⎯⎯⎯⎯⎯');
Array.from(mySet).reduceRight((_, v, i) => console.log(`i = ${i}; v = ${v}`), null);
console.log('⎯⎯⎯⎯⎯ Map ⎯⎯⎯⎯⎯');
Array.from(myMap).reduceRight((_, [k, v]) => console.log(`k = ${k}; v = ${v}`), null);
You could make an array, reverse it and generate a new set of it.
var mySet = new Set([1, 2, 3, 4, 5]),
reverseSet = new Set([...mySet].reverse());
console.log([...reverseSet]);

how to remove an item in a javascript array with json form

i have this json structure and I made it into an array. I was trying to remove the entry, but this code failed on me: Remove item from array if it exists in a 'disallowed words' array
var historyList = []; // assuming this already has the array filled
function add() {
var newHistory = {
ID: randomString(),
Name: $('#txtVaccineName').val(),
DoseDate: doseDate,
ResultDate: resultDate,
Notes: $('#txtResultNotes').val()
};
historyList.push(newHistory);
};
function removeEntry(value) {
historyList.remove('ID', value);
};
Array.prototype.remove = function(name, value) {
array = this;
var rest = $.grep(this, function(item) {
return (item[name] != value);
});
array.length = rest.length;
$.each(rest, function(n, obj) {
array[n] = obj;
});
};
You could use a property filter to match the item in your history list. Below is the sample quick code to do so, I've modified your history list a bit.
A quick test in FF, shows that it works!
var historyList = []; // assuming this already has the array filled
function addToHistory(name, notes) {
var newHistory = {
ID: new Date().getTime(),
Name: name,
DoseDate: "Somedate",
ResultDate: "SomeResultDate",
Notes: notes,
toString: function() {return this.Name;}
};
historyList.push(newHistory);
};
var Util = {};
/**
* Gets the index if first matching item in an array, whose
* property (specified by name) has the value specified by "value"
* #return index of first matching item or false otherwise
*/
Util.arrayIndexOf = function(arr, filter) {
for(var i = 0, len = arr.length; i < len; i++) {
if(filter(arr[i])) {
return i;
}
}
return -1;
};
/**
* Matches if the property specified by pName in the given item,
* has a value specified by pValue
* #return true if there is a match, false otherwise
*/
var propertyMatchFilter = function(pName, pValue) {
return function(item) {
if(item[pName] === pValue) {
return true;
}
return false;
}
}
/**
* Remove from history any item whose property pName has a value
* pValue
*/
var removeHistory = function(pName, pValue) {
var nameFilter = propertyMatchFilter(pName, pValue);
var idx = Util.arrayIndexOf(historyList, nameFilter);
if(idx != -1) {
historyList.splice(idx, 1);
}
};
// ---------------------- Tests -----------------------------------
addToHistory("history1", "Note of history1");
addToHistory("history2", "Note of history2");
addToHistory("history3", "Note of history3");
addToHistory("history4", "Note of history4");
alert(historyList); // history1,history2,history3,history4
removeHistory("Name", "history1");
alert(historyList); // history2,history3,history4
removeHistory("Notes", "Note of history3");
alert(historyList); // history2,history4
The entire Array.prototype.remove function can be inlined as follows:
function removeEntry(value) {
historyList = $.grep(historyList, function(item) {
return (item.ID !== value);
});
}
You can, of course, create a function to wrap $.grep or the predicate as you wish. (And if you do, you probably don't want to modify Array.prototype; prefer modifying historyList itself (using Array.prototype.splice) or creating a (likely static) function elsewhere.)
Also, this problem does not relate to the SO question you mention in your question, as far as I can tell.

Associative arrays in javascript

I have this object:
function formBuddy()
{
var fields = new Array();
var labels = new Array();
var rules = new Array();
var count=0;
this.addField = function(field, label, rule)
{
fields[count] = field;
labels[field] = label;
rules[field] = rule;
count = ++count;
}
}
Its used in this way:
var cForm=new formBuddy();
cForm.addField("c_first_name","First Name","required");
cForm.addField("c_last_name","Last Name","required");
The problem is, in the addField() function the fields array is being set correct (perhaps because a numerical index is being used to refer to it) but the other 2 arrays (labels and rules) aren't being touched at all. Doing a console.log shows them as empty in firebug.
What do I need to change to make them work? I'd still like to refer to the rules and labels by the string index of the field.
Use objects instead:
function formBuddy()
{
var fields = {};
var labels = {};
var rules = {};
var count = 0;
this.addField = function(field, label, rule)
{
fields[count] = field;
labels[field] = label;
rules[field] = rule;
count++;
}
}
But as Christoph already mentioned, I would store this information in a single data structure too. For example:
function formBuddy() {
var fields = {};
this.addField = function(name, label, rule) {
fields[name] = {
name: name,
label: label,
rule: rule
};
};
this.getField = function(name) {
return fields[name];
};
}
var cForm=new formBuddy();
cForm.addField("c_first_name","First Name","required");
cForm.addField("c_last_name","Last Name","required");
alert(cForm.getField("c_last_name").label);
fields should be an array, whereas labels and rules should be objects as you want to use strings as keys. Also, addField() is the same for each instance of FormBuddy() (names of constructor functions should be capitalized) and should reside in the prototype, ie
function FormBuddy() {
this.fields = []; // this is the same as `new Array()`
this.labels = {}; // this is the same as `new Object()`
this.rules = {};
}
FormBuddy.prototype.addField = function(field, label, rule) {
this.fields.push(field);
this.labels[field] = label;
this.rules[field] = rule;
};
You can access the labels/rules via
var buddy = new FormBuddy();
buddy.addField('foo', 'bar', 'baz');
alert(buddy.labels['foo']);
alert(buddy.rules.foo);
Just to further enrage Luca ;), here's another version which also dosn't encapsulate anything:
function FormBuddy() {
this.fields = [];
}
FormBuddy.prototype.addField = function(id, label, rule) {
var field = {
id : id,
label : label,
rule : rule
};
this.fields.push(field);
this['field ' + id] = field;
};
FormBuddy.prototype.getField = function(id) {
return this['field ' + id];
};
var buddy = new FormBuddy();
buddy.addField('foo', 'label for foo', 'rule for foo');
It's similar to Gumbo's second version, but his fields object is merged into the FormBuddy instance. An array called fields is added instead to allow for fast iteration.
To access a field's label, rule, or id, use
buddy.getField('foo').label
To iterate over the fields, use
// list rules:
for(var i = 0, len = buddy.fields.length; i < len; ++i)
document.writeln(buddy.fields[i].rule);
Arrays are treated as Objects in Javascript, therefore your piece of code works, it's just that firebug's console.log isn't showing you the "Objects" inside the array, rather just the array values ...
Use the for(var i in obj) to see what objects values the Array contains:
function formBuddy() {
var fields = new Array();
var labels = new Array();
var rules = new Array();
var count=0;
this.addField = function(field, label, rule)
{
fields[count] = field;
labels[field] = label;
rules[field] = rule;
count = ++count;
for(var i in labels) {
console.log(labels[i]);
}
for(var i in rules) {
console.log(rules[i]);
}
console.log(labels.c_last_name);
// or
console.log(labels["c_last_name"]);
}
}
var cForm = new formBuddy();
cForm.addField("c_last_name","Last Name","required");
Is this an alternative to what you are seeking ?
Try it.
<script type="text/javascript">"use strict";
function formBuddy() {
this.fields = new Array();
this.labels = new Array();
this.rules = new Array();
this.count=0;
this.addField = function(field, label, rule)
{
this.fields[this.count] = field;
this.labels[field] = label;
this.rules[field] = rule;
this.count++;
}
}
var cForm = new formBuddy();
// FILLING IN THE DATABASE
cForm.addField("c_first_name","Diasoluka","duplicated");
cForm.addField("c_Middle_name","Nz","inspect");
cForm.addField("c_last_name","Luyalu","mandatory");
cForm.addField("c_first_name","Diasoluka","duplicated");
console.log(`ACCESSING EACH PROPERTY INDIVIDUALLY\n,${'.'.repeat(31)}`);
let el=Object.entries(cForm.fields); // DESTRUCTURING
console.log(Object.is(el,Object.entries(cForm.fields)));
// false
const [f1,f2,f3] = el; // DESTRUCTURING=DÉCOMPOSITION
console.log("FIELDS:\n",f1," | ",f2," | ",f3,"\n\n");
// FIELDS:
// Array [ "0", "c_first_name" ]
// Array [ "1", "c_Middle_name" ]
// Array [ "2", "c_last_name" ]
let labels = Object.entries(cForm.labels); // DESTRUCTURING
const [l1,l2,l3] = labels; // DESTRUCTURING
console.log("LABELS:\n",l1," | ",l2," | ",l3,"\n\n");
// LABELS:
// Array [ "c_first_name", "Diasoluka" ]
// Array [ "c_Middle_name", "Nz" ]
// Array [ "c_last_name", "Luyalu" ]
let rules = Object.entries(cForm.rules); // DESTRUCTURING
const [r1,r2,r3] = rules; // DESTRUCTURING
console.log("RULES:\n",r1," | ",r2," | ",r3,"\n\n");
// RULES:
// Array [ "c_first_name", "duplicated" ]
// Array [ "c_Middle_name", "inspect" ]
// Array [ "c_last_name", "mandatory" ]
console.log(`PAESING THE DATABASE =\nACCESSING ALL THE FIELDS AT ONCE\n,${'.'.repeat(31)}`);
for(let key in cForm.fields){
let el=cForm.fields[key]; // ASSIGNMENT=AFFECTATION
console.log(Object.is(el,cForm.fields[key]));
// true true true true
console.log(`${el} // ${cForm.labels[el]} // ${cForm.rules[el]}\n`);
}
// c_first_name // Diasoluka // duplicated
// c_Middle_name // Nz // inspect
// c_last_name // Luyalu // mandatory
// c_first_name // Diasoluka // duplicated
console.log("\n");
console.log(`THE INNER STRUCTURE OF OUR cForm OBJECT\n,${'.'.repeat(31)}`);
console.log(Object.entries(cForm)); // DESTRUCTURING
// (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
// 0: (2) ['fields', Array(4)]
// 1: (2) ['labels', Array(0)]
// 2: (2) ['rules', Array(0)]
// 3: (2) ['count', 4]
// 4: (2) ['addField', ƒ]
// length: 5
// [[Prototype]]: Array(0)
</script>

Hash table in JavaScript

I am using a hash table in JavaScript, and I want to show the values of the following in a hash table
one -[1,10,5]
two -[2]
three -[3, 30, 300, etc.]
I have found the following code. It works for the following data.
one -[1]
two -[2]
three-[3]
How do I assign one-[1,2] values to a hash table and how do I access it?
<script type="text/javascript">
function Hash()
{
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_value;
if (typeof(this.items[in_key]) != 'undefined') {
this.length--;
var tmp_value = this.items[in_key];
delete this.items[in_key];
}
return tmp_value;
}
this.getItem = function(in_key) {
return this.items[in_key];
}
this.setItem = function(in_key, in_value)
{
if (typeof(in_value) != 'undefined') {
if (typeof(this.items[in_key]) == 'undefined') {
this.length++;
}
this.items[in_key] = in_value;
}
return in_value;
}
this.hasItem = function(in_key)
{
return typeof(this.items[in_key]) != 'undefined';
}
}
var myHash = new Hash('one',1,'two', 2, 'three',3 );
for (var i in myHash.items) {
alert('key is: ' + i + ', value is: ' + myHash.items[i]);
}
</script>
How do I do it?
Using the function above, you would do:
var myHash = new Hash('one',[1,10,5],'two', [2], 'three',[3,30,300]);
Of course, the following would also work:
var myHash = {}; // New object
myHash['one'] = [1,10,5];
myHash['two'] = [2];
myHash['three'] = [3, 30, 300];
since all objects in JavaScript are hash tables! It would, however, be harder to iterate over since using foreach(var item in object) would also get you all its functions, etc., but that might be enough depending on your needs.
If all you want to do is store some static values in a lookup table, you can use an Object Literal (the same format used by JSON) to do it compactly:
var table = { one: [1,10,5], two: [2], three: [3, 30, 300] }
And then access them using JavaScript's associative array syntax:
alert(table['one']); // Will alert with [1,10,5]
alert(table['one'][1]); // Will alert with 10
You could use my JavaScript hash table implementation, jshashtable. It allows any object to be used as a key, not just strings.
The Javascript interpreter natively stores objects in a hash table. If you're worried about contamination from the prototype chain, you can always do something like this:
// Simple ECMA5 hash table
Hash = function(oSource){
for(sKey in oSource) if(Object.prototype.hasOwnProperty.call(oSource, sKey)) this[sKey] = oSource[sKey];
};
Hash.prototype = Object.create(null);
var oHash = new Hash({foo: 'bar'});
oHash.foo === 'bar'; // true
oHash['foo'] === 'bar'; // true
oHash['meow'] = 'another prop'; // true
oHash.hasOwnProperty === undefined; // true
Object.keys(oHash); // ['foo', 'meow']
oHash instanceof Hash; // true

Categories

Resources