javascript enum auto-increment? - javascript

In objc I can use the enum like this:
typedef enum {
STATE_A = 1,
STATE_B,
STATE_C,
......
STATE_KK = 100,
STATE_FF,
......
STATE_XXX = 99999
} State;
the value of each variable is auto increased (compared to the former one).
but in javascript, I need to:
var State = {
STATE_A: 1,
STATE_B: 2,
STATE_C: 3,
......
STATE_KK: 100,
STATE_FF: 101,
......
STATE_XXX = 99999
}
you see I need to specify all the values for each varible and this is really sick when you
got lots of varible there and it gets even sicker when you try to insert a variable in between so that
you have to ask yourself (what the value it should be ???)
I'm quite new to js and really wants to know if there is a way to use enum in js the way like in other languages
such as objc I mentioned.
Thanks :)

its kind of ugly, but you could do:
var i=1;
var State = {
STATE_A: i++,
STATE_B: i++,
STATE_C: i++
}

How about giving them all an initial value of 0 then setting their values in a loop
var State = {
STATE_A: 0,
STATE_B: 0,
STATE_C: 0,
......
STATE_KK: 0,
STATE_FF: 0,
......
STATE_XXX = 0
}
var count=0;
for(var key in State){
State[key]=count++;
}

You can create your little enum maker that both auto-numbers them and lets you set any values you want (kind of like the features you have in objectiveC:
function makeEnum(list) {
var obj = {}, sequence = 0, current;
for (var i = 0; i < list.length; i++) {
current = i;
if (typeof list[i+1] === "number") {
sequence = list[i+1];
i++;
}
obj[list[current]] = sequence++;
}
return(obj);
}
var State = makeEnum(["STATE_A","STATE_B","STATE_C", "STATE_KK", 100, "STATE_LL"]);
Anywhere you put a number in the passed in array, it sets the value of the previous enum value and the sequence then continues from that value.

If I understand correctly your goal is to identify states with numbers in order to make them comparable in enums.
First here is a working fiddle of what I think you meant.
For general enums, here is a nice trick I use:
function createEnum(values){
var res={};
for(var i=0;i<values.length;i++){
res[values[i]]=i;//add the property
}
//Object.freeze(res);//optional to make immutable
return res;
};
This allows the following syntax
var State = createEnum(["STATE_A","STATE_B","STATE_C"]);
This means you don't have to explicitly define an integer value for all the states, one is given. After that you can use it normally
State.STATE_A===State.STATE_B;//returns 1
If you'd like to fill based on a pattern, you can extend this the following way (assuming your syntax):
function createEnumPattern(prefix,range){
var res={},str="a";
for(var i=0;i<range;i++){
var pattern = prefix+"_"+inc_str(str);
res[pattern]=i;//add the property
}
//Object.freeze(res);//optional to make immutable
return res;
}
Where inc_str is from this answer.
So for example
var State = createEnumPattern("State",100);
Will return a State enum with properties like State_aa and so on, if you'd like you can use toUpperCase on it to force the upper case convention you use.

Related

Searching AFINN-165 json by score

I'm making a emotion-adjusted Youtube search engine which maps a score (read from webcam images by Microsoft Azure Emotion API) to a few words selected in the AFINN-165 list, and then peforms a Youtube search.
The code is written in Node & Express (returns the answer by GET request).
I'm trying to search the JSON by value of a word. Example; When I give the function (5) it would return all words that have a score of five.
The JSON is structured like this:
var data = {
word: score,
word: score,
word: score,
};
Which I wrap in an array below
function getWordsByScore() {
var afinnKeys = Object.keys(afinn);
var afinnArray = [afinn]
console.log(afinnKeys.length);
for (var i = 0; i < afinnKeys.length; i++) {
var word = String(afinnKeys[i]);
return(afinnArray[0].word);
}
}
Somehow I just can't get it to work. I try to get the actual 'word' by creating an array of keys in AfinnKeys. But feeding this word by a forloop to the afinnArray[0] just gives undefined as a return.
I hope someone could help me out. Have been stuck on this for some time now.
Would something like this help you?
var score = 3;
var data = {
'firstword': 1,
'secondword': 2,
'thirdword': 3,
'forthword': 3
};
var result = Object.keys(data).filter(function (key) {
return data[key] === score
});
console.log(result);
The reason you're getting undefined is because your for loop runs once and then returns immediately.
The value it tries to return is afinnArray[0].word which looks for the property word on the afinnArray[0] object when you may have meant to do afinnArray[0][word] which uses the string variable word as the property name.
You also never pass the score to the function so as it is it won't be based on the score.
All you really need to do is to compare the score passed in to the function to the score in the afinn object by using the word from the word variable obtained your for loop as the key (and it's already a string so there's no need to cast it to one). Then, if the scores match, push the word to a new array. Once the for loop completes, return the new array.
var afinn = {
a: 1,
b: 1,
c: 0,
d: 0,
e: 2,
f: 2
};
function getWordsByScore(score) {
var afinnKeys = Object.keys(afinn);
var afinnArray = []
for (var i = 0; i < afinnKeys.length; i++) {
var word = afinnKeys[i];
if(afinn[word] == score){
afinnArray.push(word)
}
}
return afinnArray
}
console.log(getWordsByScore(1))
Or as another commenter suggested, use Array#filter

What's the easiest way to store and load data Javascript?

I have a Hashmap for storing Loudness values. The code is in Javascript HTML5.
var Loudness = {};
Loudness['f125'] = {right: [], left: []};
Loudness['f125']['right'].push([0,10,30, 40]);
Loudness['f125']['left'].push([5,15,35,45]);
Loudness['f250'] = {right: [], left:[] };
Loudness['f500'] = {right: [], left: []};
Loudness['f1000'] = {right: [], left: []};
I also have a Hashmap for storing Gain values (basically the same as up, also w/ "right" and "left" (right and left side of the audiospeakers) properties.
The difference is the name of the HM and the values of the array. I have a lot of frequencies (keys, for instance f250, f500, …) still to insert to each Hashmap. Is there a more efficient way to declare each frequency key and its properties?
Does it make sense to use a Hashmap inside a Hashmap?
Also, if the Gain HM is put inside the Loudness HM, how would the new Loudness HM disposition be like? Do the keys(frequencies) remain the same? Is the GainHashmap now a new property?
I haven’t found how to implement it. What would the syntax be like?
What's the easiest way to insert and easily change data ("loudness" and "gain" for "right" and "left", for each frequency).
Is there a better option in your opinion? WebStorageAPI, Hashmap inside Hashmap?
Please consider that I'm not such an expert in programming. Any help is greatly Appreciated.
var Loudness = {};
var freqs = ['f125', 'f250', 'f500', 'f1000', 'f1250'];
var values = [0, 10, 30, 40, 5, 15, 35, 45];
for(var i in freqs){
Loudness[freqs[i]] = {left : [], right : []};
Loudness[freqs[i]].Gain = {left : [], right : []};
for(var j in values){
var v = values[j];
if(v === 0 || v % 2 === 0){
Loudness[freqs[i]]['right'].push(v);
Loudness[freqs[i]].Gain['right'].push(v);
} else {
Loudness[freqs[i]]['left'].push(v);
Loudness[freqs[i]].Gain['left'].push(v);
}
}
}
Try this one. In order to access your gains:
Loudness['f125'].Gain.left[0]
Basically if you need more frequencies, just add them to freqs arrays.
So, the idea of Gain as property inside the Loudness HM is perfect.
The problem is that this Loudness HM is not allowed to be accessed (wherever and however it was declared).
1) I tried to make it acessible even through privileged methods returning it.
2) I even declared it inside a constructor (using this.Loudness = {}; instead of var Loudness = {};, but am receiving errors like "Uncaught TypeError: Cannot read property '250' of undefined", when trying to access this value. Piece of the public method which uses it:
AudiometrySample.prototype.loudnessToGain = function (frequency, loudness, activeChannel) {
...
console.log("this.Loudness[250] is"+ this.Loudness);
if (this.activeChannel === "right") {
for (var j = 0; j < this.Loudness[this.frequency].right.length; j++) {
if (this.Loudness[this.frequency].right[j] === this.loudness) {
this.wantedGain = this.Loudness[this.frequency].Gain.right[j];
this.currentPairIndex = j;
}
}
}
This console log gives "undefined" back. How to make it accessible?

How to return an array of numbers from a function in asm.js?

I'm sure I could eventually figure this out, but the documentation is a bit verbose and I think this ought to be a common question about asm.js.
Here goes:
Suppose that I have a function that looks like this:
function computeSquares() {
var i, array = [];
for(i = 0; i < 100; i++) {
array.push(i * i);
}
return array;
}
The above function computes the square of the integers from 0 to 99 and returns an array containing the results.
I would like to write a function like this in asm.js that returns an object containing the 100 square values. If I've read the documentation, I'm supposed to use the ArrayBuffer object, but I'm a bit confused about how to do it.
Please illuminate me by giving an example of how to code this with asm.js.
You can only return doubles, signed ints and voids from exported functions. If you want to return an array you'll have to write it into the heap.
The module would look like this:
function squaresModule(stdlib, foreign, heap) {
"use asm";
var imul = stdlib.Math.imul;
var array = new stdlib.Uint32Array(heap);
function compute( max ){
max = max|0; //max is an integer
var i = 0;
for( i = 0; (i|0) < (max|0); i = (i+1)|0 ) {
array[ i <<2>>2 ] = imul(i, i)|0;
}
return 0; //asm functions have to return a number
}
return {compute:compute};
}
.
Then use execute and log the array:
var array = Uint32Array( 100 );
var module = squareModule(
{Math:Math,Uint32Array:Uint32Array}, {}, array.buffer
);
module.compute(100);
console.log(array);
Instead of returning an array, I write the results in a convenient representation inside asm.js and then extract it with a wrapper function in JS that repeatedly calls into asm.js code to get the next value:
var result = [];
var i = 0;
while (true) {
i = return_next_array_value_from_asmjs();
if (i !== 0) {
result.push(i);
} else {
break;
}
}
The downside is that you need to reserve at least one value as a stop marker. I have not tested the performance because I couldn't get any other method to work.

assign variable 1 to variable 2 and variable 2 to variable 3 javascript

i've got an array, and i want to shuffle those according to a certain pattern
(i'm trying to make a rubics cube in javascript).
I want to assign value2 to value 1 and value 1 to value 3 and value 3 to value 2. I can do that within 4 lines of code, but is there a shorter way?
like:
temp = var3; //make temporary variable
(var3 = var2) = var1;//put var2 in var3 and var3 in var1
var1 = temp;//put var3/temp in var1
i know that it doesn't work this way, but do you guys know a way it does work?
that would be usefull when cycling 8 variables.
thanks,
Tempestas Ludi.
If you're dealing with more than 2 variables, it's always best to use an array, since arrays have built in functions you can use
var nums = [1,2,3]; // this is your array. it can have any length you want
// this is one line that does the magic
nums.push(nums.shift()); // to the left
nums.unshift(nums.pop()); // to the right
http://jsfiddle.net/wbKYY/2/
http://jsfiddle.net/wbKYY/4/
Anyway, about your comment. Seeing as the pointers which you will rotate aren't predetermined, and will vary, it's probably best to use a function.A function that will iterate through pointers that you define.
function rotateArr(arr,pointers,dir) {
var narr = arr; // create a local copy we can use it
var savevalue;
if (dir == 1) { // rotate to the right
savevalue = narr[pointers[pointers.length-1]]; // save the last value
for(var i=pointers.length-2;i>=0;i--) {
narr[pointers[i+1]] = narr[pointers[i]];
}
narr[pointers[0]] = savevalue; // set the first value
} else { // rotate to the left
savevalue = narr[pointers[0]]; // save the first value
for(var i=0;i<pointers.length-1;i++) {
narr[pointers[i]] = narr[pointers[i+1]];
}
narr[pointers[pointers.length-1]] = savevalue; // set the last value
}
return narr;
}
// arr is the array of faces
// pointers is the elements which you want to rotate (an array)
// dir is either 1 or -1
you can execute this function with
nums = rotateArr(nums,[pointers],[1,-1]);
// just some examples
nums = rotateArr(nums,[0,1,2,5],1);
nums = rotateArr(nums,[3,6,1,4],-1);
Here's a working example:
http://jsfiddle.net/w2jGr/
However if you prefer to use a prototype function that is just a method of an array, you can define a property and just access it from there.
Object.defineProperty(Object.prototype, "rotateArr", { value: function(pointers,dir) {
var savevalue;
if (dir == 1) { // rotate to the right
savevalue = this[pointers[pointers.length-1]]; // save the last value
for(var i=pointers.length-2;i>=0;i--) {
this[pointers[i+1]] = this[pointers[i]];
}
this[pointers[0]] = savevalue;
} else { // rotate to the left
savevalue = this[pointers[0]]; // save the last value
for(var i=0;i<pointers.length-1;i++) {
this[pointers[i]] = this[pointers[i+1]];
}
this[pointers[pointers.length-1]] = savevalue;
}
}, enumerable : false});
Modifying the prototype of an object is never recommended, but if you aren't going for clean code and want usability or readability, this works great as you can call the function with
nums.rotate([pointers],dir);
http://jsfiddle.net/w2jGr/1/
Why not put your values in an array, and just change the index pointer when you want to use different values?

JavaScript converting an array to array of functions

Hello I'm working on a problem that requires me to change an set array of numbers into an array that returns the original numbers as a function. So we get a return of a2 instead of a[2].
I dont want the answer I just need a hint. I know i can loop through the array and use .pop() to get the last value of the array, but then I dont know how to convert it to a function from there. any hints?
var numToFun = [1, 2, 3];
var numToFunLength = numToFun.length;
for (var i = 0; i < numToFunLength; i++) {
(function(num){
numToFun.unshift(function() {
return num;
});
}(numToFun.pop()))
}
DEMO
basically it pops out a number from the last, builds a function with that number returned, and put back into the first of the array. after one full cycle, all of them are functions.
here's the catch: how this works, it's up to you to research
why the loop does not look like the straightforward pop-unshift:
for (var i = 0; i < numToFunLength; i++) {
numToFun.unshift(function() { //put into first a function
return numToFun.pop() //that returns a number
});
}
and why i did this: (HINT: performance)
var numToFunLength = numToFun.length;
There's three important steps here:
Extract the number value from the array. Within a loop with an iterator of i, it might look like this:
var num = numArray[i];
This is important, because i will not retain its value that it had when you created the new function - it'll end up with the last value it had, once the for loop is finished. The function itself might look like this:
function() { return num; }
There's no reference to i any more, which is important - to understand better, read about closures. The final step would be to add the new function to the array of functions that you want.
...and you're done!
EDIT: See other's answers for good explanations of how to do this right, I will fix mine also though
As others have pointed out, one of the tricky things in javascript that many struggle with (myself included, obviously) is that scoping variables in javascript is dissimilar to many other languages; scopes are almost purely defined by functions, not the {} blocks of, for example, a for loop, as java/C would be.
So, below you can see (and in other answers here) a scoping function can aid with such a problem.
var numArray = [12, 33, 55];
var funcArray = [];
var numArrLength = numArray.length; // Don't do this in for loop to avoid the check multiple times
for(var j=0; j < numArrLength; j++) {
var scopeMe = function() {
var numToReturn = numArray[j];
console.log('now loading... ' + numToReturn);
var newFunc = function() {
return numToReturn;
};
return newFunc;
}();
funcArray.push(scopeMe);
};
console.log('now me');
console.log(funcArray);
console.log(funcArray[0]());
console.log(funcArray[1]());
console.log(funcArray[2]());
console.log(funcArray[1]()); // To ensure it's repeatable
EDIT my old bad answer below
What you'll want to do is something like
var funcArray = [];
for(...) {
var newFunc = function() {
return numArray.pop();
}
funcArray.push(newFunc);
}
The key here is that functions in javascript can be named variables, and passed around as such :)

Categories

Resources