Javascript for loop not appending list in dictionary - javascript

And I'm not sure I understand the problem at all.
var vtf=[]; // Dictionary that maps number-> list
var length;
var s; // A list of numbers with s.length = length
// length and s are set to values
for(i=0; i<length; i++)
{
var f=s[i];
if(f in vtf)
vtf[f].push(i);
else
vtf[f]=[i];
}
So basically I check if vtf contains the value f=s[i]. If it does it appends i to the list contained at vtf[f] and if it doesn't it makes a new list with i as its only element.
The problem I get is that after running this every index of vtf only contains that first i that was added despite me knowing that almost every value saved in vtf should have a list of multiple elements.
I can't understand what I'm doing wrong. When I put alerts inside the if statement they don't even pop up but when I put them outside the loop, for the same value, they show it's evaluating to true a number of times.

Your code is correct, the only thing, vtf should be declared as an object, not as an array:
var vtf={};
var s=[1,2,3,4,1,2,3,4];
for(i=0; i<s.length; i++)
{
var f=s[i]; // All values in s are numbers
if(f in vtf)
vtf[f].push(i);
else
vtf[f]=[i];
}
console.log(JSON.stringify(vtf))
Result:
"{"1":[0,4],"2":[1,5],"3":[2,6],"4":[3,7]}"

Related

Apps Script JS adding items to array from range (if not already in array) fails

I am looping through various cells and want to add their string content do an array, if the content is not already in the array. It works perfectly fine when I do it manually like so, trying to add 'eJobs' to the array (see below "var item = 'eJobs') which already containts 'eJobs':
var divisionarray = ['eJobs']
for (var i = 0; i < cells_users.length-1; ++i) {
var row_users = cells_users[i];
if (row_users[0] == user_ldap) {
var podarray = row_users[1].split(', ')
for (j = 0; j < podarray.length; j++) {
for (var k = 0; k < cells_edit.length; ++k) {
var row_edit = cells_edit[k]
if (podarray[j] === row_edit[0]) {
var item = 'eJobs'
if (!(divisionarray.indexOf(item) >= 0)) {
divisionarray.push(item)
}
}
}
}
Logger.log(divisionarray)
As expected, the log file shows [17-10-08 19:11:04:111 BST] [eJobs], illustrating that the code works and 'eJobs' has not been added to the array as it is already in the array.
Now, when I change var item='eJobs' to values of a range
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
the code does not work anylonger, as the log file shows:
[17-10-08 19:14:03:770 BST] [eJobs, eJobs, BestJobs, Vivre Deco, ...
Note I have a range of thousands of cells, so I get alot of duplicates added. What am I missing? Note the cells of the defined range are indeed just strings with a single word (e.g. 'eJobs').
The code is working and the log file is indicating what the problem is..
[eJobs, eJobs, BestJobs, Vivre Deco,
In the second eJobs there is a white space before eJobs, so the first value and the second value don't match.
Without seeing your data and going by the 'just strings with a single word' I would say that using a .replace(" ", "") on the text string should work, this will find the first " " in the string and remove it. I.e. " eJobs" would become "eJobs".
2.
Is this line of code just for testing? You should never use a method like this in a script. It will be extremely inefficient
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
Instead get the full range using .getValues()and iterate over it then.
3.
Is there a reason you are using === in if (podarray[j] === row_edit[0]) unless you need to check for type always use ==

Iterating through an array until random value isn't equal to anything

First of all, I am very new to programming so apologies in advance.
This is what I am trying to do:
1) Generate a random value into a variable using
questionNr = Random.Range(0, nNodes);
2) Compare that variable to an array by iterating through all its values
for(var i=0; i<usedQuestionList.length(); i++){
if(questionNr == usedQuestionList[i]){
//stuff
}
}
3) If any value of the array is equal to said variable's value, start from the beginning by generating a new random value and loop through the array again. The only way to pass/end the loop is when the random value is NOT equal to any of the values in the array.
The problem is that if I do this simple for loop, there's no way for me to go back and do everything again when the conditions are not met.
I'm pretty sure I'm just approaching the logic wrong and there's a simple way to do this that hasn't occurred to me, that's why I'm not adding any of the code from my failed for and while loop attempts. Any help appreciated, thanks!
You can set a flag that you can check after the loop has finished, maybe something like this:
//A function that will take a number and check against the array
var loopRandomNumber = function(number){
//A flag to be used if match is found
var foundMatch = false;
//Your simple loop
for(var i=0; i<usedQuestionList.length(); i++){
//Checking if match
if(number == usedQuestionList[i]){
foundMatch = true; //Match found
break; // Jumps out of the for-loop to be a little faster
}
}
//Calling this function again with a new random number if match found
if(foundMatch){
loopRandomNumber(Random.Range(0, nNodes));
} else {
//Handle your condition for if no match was found here
}
}
loopRandomNumber(Random.Range(0, nNodes));

Javascript: Iterating over an array causes an infinite loop?

I'm trying to iterate over some data in Javascript, using the following code:
for (var i = 0; i < fromdata.length; i++) {
var mainid = fromdata[i].id;
var sub = afcHelper_Submissions[mainid];
/* do more stuff */
fromdata is an array of Objects that looks something like this:
[{ type="ffu", to=" Jon Corzine ", id=1, more...}, { type="ffu", to=" Jon Corzine ", id=2, more...}]
As you can see, I just want to get each object's id and store it to mainid and then do some more with it; however, I run into trouble: looping! Looping! Looping! The loop keeps running again and again. It never stops, and just manages to freeze up Firebug.
Update: Here's the "do more stuff", in all its pastebin glory: http://pastebin.com/Mfr90uq7. Note that I changed the variable name from sub to sub_m to avoid a potential conflict, but the problem persisted.
A loop only can be infinite if the condition is always true. In your case it looks that it should reach a false , but provably formData is getting new elements each iteration of the loop or i is being modified and returned to previous values.
What I recomend is to create variables that will be used only for comparasion purposes:
var max = fromdata.length;
for (var count = 0; count < max; count++) {
var i = count;
// your stuff using formdata and i
Now max and count will not be modified by the code in the loop and the loop will reach an end.

Get array values and put them into different divs with a for loop?

I'm trying hard to learn javascrip+jquery on my own, and also trying to learn it right. Thus trying to enforce the DRY rule.
I find myself stuck with a problem where I have an array,
var animals = [4];
a function,
var legs = function(amount){
this.amount = amount;
this.body = Math.floor(Math.random()*amount)+1;
}
and an evil for loop. I also have 5 div's called printAnimal1, printAnimal2 and so on.. In which I wish to print out each value in the array into.
for(i = 0; i < animals.length; i++){
animals[i] = new legs(6);
$(".printAnimal"+i).append("animals[i]");
}
I feel as if I'm close to the right thing, but I cant seem to figure it out. I also tried something like this:
for(i = 0; i < animals.length; i++){
animals[i] = new legs(6);
$this = $(".printAnimal");
$(this+i).append("animals[i]");
}
But one of the problems seem to be the "+i" and I cant make heads or tails out of it.
I also know that I can simply do:
$(".printAnimal1").append("animals[i]");
$(".printAnimal2").append("animals[i]");
$(".printAnimal3").append("animals[i]");
...
But that would break the DRY rule. Is it all wrong trying to do this with a for loop, or can it be done? Or is there simply a better way to do it! Could anyone clarify?
Your first attempt should be fine, as long as you take "animals[i]" out of quotes in your append() call ($(".printAnimal"+i).append(animals[i]))
Also, I assume you declared var i; outside your for loop? If not, you'll want to declare it in your for loop (for(var i=0....)
EDIT: problems with your fiddle
you never call startGame()
you didn't include jQuery
you can't (as far as I know) append anything that isn't html-- in your case, you're trying to append a js object. What do you want the end result to look like?
http://jsfiddle.net/SjHgh/1/ is a working fiddle showing that append() works as you think it should.
edit: forgot to update the fiddle. Correct link now.
EDIT: reread your response to the other answer about what you want. http://jsfiddle.net/SjHgh/3/ is a working fiddle with what you want. More notes:
You didn't declare new when you called DICE
you have to reference the field you want, (hence dices[i].roll), not just the object
Just a few comments:
This is declaring an array with only one item and that item is the number 4
var animals = [4];
In case you still need that array, you should be doing something like:
var animals = []; // A shiny new and empty array
and then add items to it inside a for loop like this:
animals.push(new legs(6)); //This will add a new legs object to the end of the array
Also, what is the content that you are expecting to appear after adding it to the div?
If you want the number of legs, you should append that to the element (and not the legs object directly).
for(i = 0; i < animals.length; i++){
animals.push(new legs(6));
$(".printAnimal"+i).append(animals[i].body);
}
Adding another answer as per your comment
var i, dicesThrown = [];
function throwDice(){
return Math.ceil(Math.random() * 6);
}
//Throw 5 dices
for (i=0 ; i<5 ; i++){
dicesThrown.push( throwDice() );
}
//Show the results
for (i=0 ; i<5 ; i++){
$("body").append("<div>Dice " + (i+1) + ": " + dicesThrown[i] +"</div>");
}

Can I select 2nd element of a 2 dimensional array by value of the first element in Javascript?

I have a JSON response like this:
var errorLog = "[[\"comp\",\"Please add company name!\"],
[\"zip\",\"Please add zip code!\"],
...
Which I'm deserializing like this:
var log = jQuery.parseJSON(errorLog);
Now I can access elements like this:
log[1][1] > "Please add company name"
Question:
If I have the first value comp, is there a way to directly get the 2nd value by doing:
log[comp][1]
without looping through the whole array.
Thanks for help!
No. Unless the 'value' of the first array (maybe I should say, the first dimension, or the first row), is also it's key. That is, unless it is something like this:
log = {
'comp': 'Please add a company name'
.
.
.
}
Now, log['comp'] or log.comp is legal.
There are two was to do this, but neither avoids a loop. The first is to loop through the array each time you access the items:
var val = '';
for (var i = 0; i < errorLog.length; i++) {
if (errorLog[i][0] === "comp") {
val = errorLog[i][1];
break;
}
}
The other would be to work your array into an object and access it with object notation.
var errors = {};
for (var i = 0; i < errorLog.length; i++) {
errors[errorLog[i][0]] = errorLog[i][1];
}
You could then access the relevant value with errors.comp.
If you're only looking once, the first option is probably better. If you may look more than once, it's probably best to use the second system since (a) you only need to do the loop once, which is more efficient, (b) you don't repeat yourself with the looping code, (c) it's immediately obvious what you're trying to do.
No matter what you are going to loop through the array somehow even it is obscured for you a bit by tools like jQuery.
You could create an object from the array as has been suggested like this:
var objLookup = function(arr, search) {
var o = {}, i, l, first, second;
for (i=0, l=arr.length; i<l; i++) {
first = arr[i][0]; // These variables are for convenience and readability.
second = arr[i][1]; // The function could be rewritten without them.
o[first] = second;
}
return o[search];
}
But the faster solution would be to just loop through the array and return the value as soon as it is found:
var indexLookup = function(arr, search){
var index = -1, i, l;
for (i = 0, l = arr.length; i<l; i++) {
if (arr[i][0] === search) return arr[i][1];
}
return undefined;
}
You could then just use these functions like this in your code so that you don't have to have the looping in the middle of all your code:
var log = [
["comp","Please add company name!"],
["zip","Please add zip code!"]
];
objLookup(log, "zip"); // Please add zip code!
indexLookup(log, "comp"); // Please add company name!
Here is a jsfiddle that shows these in use.
Have you looked at jQuery's grep or inArray method?
See this discussion
Are there any jquery features to query multi-dimensional arrays in a similar fashion to the DOM?

Categories