Can't access any arrays after sorting another array - javascript

I have encountered a very strange bug:
I derive a new array allSavings[] from another one (tours[]) and sort it in the function calculateAllSavings(). Before I call the function I can access tours[] just fine, but afterwards, I can't anymore. The div tags demo1 and demo2 both exist and are working fine for other outputs.
function euclDist(node1,node2){
if(node1 != node2){
var x = Math.pow(nodes[node2].x - nodes[node1].x,2);
var y = Math.pow(nodes[node2].y - nodes[node1].y,2);
var dist = Math.sqrt(x+y);
return dist;
}
else return 0.0;
}
function tourDist(members){
var tourDist = 0.0;
if (members.length>1){
for (i = 1; i < members.length; i++)
tourDist += euclDist(members[i],members[i-1]);
}
return tourDist;
}
function combineTours(tourA, tourB){
tourA.pop();
tourB.shift();
return tourA.concat(tourB);
}
function calculateSaving(tourA,tourB){
var costSeparate = tourDist(tourA) + tourDist(tourB);
var combTour = combineTours(tourA,tourB);
var costCombined = tourDist(combTour);
return costSeparate - costCombined;
}
function calculateAllSavings(){
var allPossibilities = [];
for(var i = 0; i < tours.length; i++){
for(var j = 0; j < tours.length; j++){
if(i != j)
var savingObj = {saving:calculateSaving(tours[i],tours[j]), tourA: i, tourB: j};
allPossibilities.push(savingObj);
}
}
allPossibilities.sort(function(a, b){
return b.saving-a.saving
})
document.getElementById("demo3").innerHTML = "success";
return allPossibilities;
}
//Initialize Array
var tours = [];
tours.push([0,1,2,3,0]);
tours.push([0,4,5,6,0]);
tours.push([0,7,8,0]);
tours.push([0,9,10,0]);
//BUG
document.getElementById("demo1").innerHTML = tours.join('\n'); // Shows array correctly
var allSavings = calculateAllSavings(); //BUG APPEARS HERE
document.getElementById("demo2").innerHTML = tours.join('\n'); // Doesn't show anything
Edit Solved:
combine() was overwriting the original tours[].
by doing the combining with cloned tours, the original was left untouchted.
function combineTours(tourA, tourB){
var tour1 = tourA.slice(0);
var tour2 = tourB.slice(0);
tour1.pop();
tour2.shift();
return tour1.concat(tour2);
}
Thanks to everyone who helped me

Well, in combineTours function you're calling .pop() method on one array and .shift() method on another, which removes one element from each of these arrays. In calculateAllSavings you're calling calculateSaving in a loop and it's calling combineTours, so you're effectively removing all elements from the sub-arrays.
Maybe you should just remove these lines from combineTours:
tourA.pop();
tourB.shift();
For the future: use console.log() for debugging, it could help you identify the issue.

Can you try this?
for(var i = 0; i < tours.length; i++){
for(var j = 0; j < tours[i].length; j++){
if(i != j)
var savingObj = {saving:calculateSaving(tours[i],tours[j]), tourA: i, tourB: j};
allPossibilities.push(savingObj);
}
}
Apart from this, you can also debug and see if your document.getElementById("demo2").innerHTML = tours.join('\n'); line actually gets executed. You may be running an infinite loop. Try and debug your code using chrome developer tools.

Related

Console.log gives correct output but when accessing set value it gives wrong output

Called Function:
this.findVerticalPossibleScoring = function(){
var possibilitySet = [];
for (var j = 0; j < 9;j++ ) {
for (var i = 0; i < 7; ){
var tempTile = this._tiles[i][j];
if(this.gameTilesValue[i][j]!=-1){
var tileTagValue = this.gameTilesValue[i][j];
if(this.gameTilesValue[i+1][j]==tileTagValue && this.gameTilesValue[i+2][j]==tileTagValue){
setElement = [];
do{
var tempPoint = this.makeArray(i,j);
setElement.push(tempPoint);
console.log(" verical i:"+i+" j:"+j);
i=i+1;
}while(i<9&&this.gameTilesValue[i][j]==tileTagValue);
possibilitySet.push(setElement);
continue;
}
}
i = i+1;
}
}
return possibilitySet;
};
this.makeArray = function (a,b){
console.log("element i:"+a+" j:"+b);
var arrayTemp = [];
arrayTemp.push(a);
arrayTemp.push(b);
return arrayTemp;
};
Calling function part:
if(scoringPossible == true){
//blast the tiles and add new tiles;
var verticalPossibleScoring = this.findVerticalPossibleScoring();
toBeDeletedTiles = [];
for(var i=0;i<verticalPossibleScoring.length;i++){
var tempSet = verticalPossibleScoring[i];
for(var j = 0;j<tempSet.length;j++){
var tempSetEntry = tempSet[i];
console.log("TILE i:"+tempSetEntry[0]+" j:"+tempSetEntry[1]);
}
}
}
I have added called function as well as calling function if loop as calling function is too big. I know this is infamous javascript loop issue. I am using gc-devkit game engine which is new and I new to it. I had solved the same issue for UIImage in it by creating custom class, but here I don't require custom array for it. Can any one guide me through this issue. Thanks in advance.
You use j as your loop variable when iterating over tempSet but then use i when getting elements from tempSet. Maybe just change
var tempSetEntry = tempSet[i];
to
var tempSetEntry = tempSet[j];

JS check if the value of object exists

So, I have following js setup:
var NAMES = [];
function INFO(id,first,middle,last){
var newMap = {};
newMap[id] = [first, middle, last];
return newMap ;
}
Then,
for (var j = 0; j < NUMBER.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
if (NAMES[my_name] !== 185){ //Needs to check here
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}else{
}
}
alert(JSON.stringify(NAMES , null, 4));
Here is a screenshot of the alert:
I hardcoded the number "185" for this example. I need to check if the id of 185 exists, then skip to else. I am not sure how to check it. I tried typeof, undefinedetc. but no luck.
(In other words, I should only have one "185").
Any help? Thanks!
If I understood correctly what you are trying to achieve, you have to iterate over NAMES and check every element. For example, you could do it using [].some javascript function:
if (!NAMES.some(function(v){return v[my_name]})) {
...
} else {
}
If you want to remove duplication you can just use NAMES as an object instead of array like this
var all_names = [185, 185, 181],
NAMES = {};
for (var j = 0; j < all_names.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
NAMES[my_name] = ["sean","sdfsd","sdfsfd"];
}
alert(JSON.stringify(NAMES, null, 4));
First of all I would recommend making a JS Fiddle or CodePen out of this so people can see the code running.
I believe that the issue is that NAMES[my_name] is not doing what you think it is. NAMES is an Array so when you say NAMES[my_name] you are really asking for the ITEM in the array so you are getting the entire object that you create in the INFO function. What you really want is to see if the object has an attribute that matches the value (e.g. "185" from the my_names array).
This is not the prettiest code but it will show you how to do what you really want to do:
var NAMES = [];
function INFO(id,first,middle,last){
var newMap = {};
newMap[id] = [first, middle, last];
return newMap ;
}
all_names = ["185", "186", "185"]
for (var j = 0; j < all_names.length; j++) {
var my_name = all_names[j];
if (NAMES.length == 0) {
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
} else {
var match = false;
for (var x = 0; x < NAMES.length; x++) {
console.log(NAMES[x][my_name] + ' : ' + my_name);
if(NAMES[x][my_name]) {
match = true;
}
}
if (!match) {
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}
}
}
alert(JSON.stringify(NAMES , null, 4));
Note the if that looks at NAMES[x][my_name] - this is asking if the item at array index 'x' has an attribute of 'my_name' (e.g. "185"). I believe this is really what you are trying to do. As its after midnight I assure you that there is more concise and pretty JS to do this but this should show you the basic issue you have to address.
Try this code using hasOwnProperty method :
for (var j = 0; j < NUMBER.length; j++) { //let say it there are three values
var my_name = all_names[j]; // has "185, 185, 185"
if (!NAMES[my_name].hasOwnProperty("185")){ //Needs to check here
NAMES.push(INFO(my_name,"sean","sdfsd","sdfsfd"));
}else{
}
}

how to access and sort 2d array in javascript

I'm writing a script to initalize 2d array in javascript by reading txt file. Here are some portions of my code
var neighbor = {};
var temp = new Array();
neighbor[nodemap[ temparray[0]]] = temp; //nodemap[ temparray[0]] is an integer
neighbor[nodemap[temparray[0]]]. push(nodemap[temparray[1]]);
neighbor[nodemap[temparray[0]]]. push(nodemap[temparray[2]]);
.... // continue to add value
Then I want to access and sort the array, like this
for (var i = 0; i < n_count; i++);
{
for (var k = 0; k < neighbor[i].length; k++);
neighbor[k].sort(function(a,b){return a - b})
}
However, I got the error that neighbor[i] is unidentified. Could you please show me how to fix that?
Your neighbor "array" is actually an object literal. So the way you should loop over neighbor is:
for (var key in neighbor) {
var cur = neighbor[key];
cur.sort(function (a,b) {
return a - b;
});
}

insert array in other array in to a for loop,first result repeated

I have a problem when inserting an array into another array in this loop:
function formToArray(frm){
var sAux={};
var AnnotationsQuestion={};
var AllAnnotationsQuestion=[];
for (i = 0; i < frm.length; i++) {
//next line dont work
sAux['question_id'] = frm[i].name.substring(13)
sAux['answer']=frm[i].value;
sAux['id']=0;
AnnotationsQuestion['AnnotationsQuestion']=sAux;
AllAnnotationsQuestion.push(AnnotationsQuestion);
}
return AllAnnotationsQuestion
}
this returns the first result repeated x times
example of a return value
[{'AnnotationsQuestion':{'question_id':4,'answer':
'AA'....}},{'AnnotationsQuestion':{'question_id':4,'answer':
'AA'....}}]
what is the problem of this loop?
This is much safer and readable
DEMO
function formToArray(frm){
var AllAnnotationsQuestion=[];
for (var i = 0; i < frm.length; i++) {
AllAnnotationsQuestion.push({
'AnnotationsQuestion': {
'question_id': frm[i].name.substring(13),
'answer': frm[i].value,
'id':0
}
});
}
return AllAnnotationsQuestion;
}

List Permutations

I'm trying to list all three letter permutations and this is the code I have -
window.permute = function(){
var alphabet = "abcdefghijklmnopqrstuvwxyz";
var searchTerm ="aaa";
var position = 2;
changeString(searchTerm, position);
}
window.changeString = function(searchTerm, position){
if (position <0){
alert(newString);
return;
}
var alphabet = "abcdefghijklmnopqrstuvwxyz"
for (j=0; j < 26;j++){
var newString = searchTerm.substr(0, position) + alphabet[j] + searchTerm.substr(position+1);
var newPosition = position -1;
changeString(newString,newPosition);
}
return;
}
It's not working and I'm not sure why- can anyone help?
var permutate = (function() {
var results = [];
function doPermute(input, output, used, size, level) {
if (size == level) {
var word = output.join('');
results.push(word);
return;
}
level++;
for (var i = 0; i < input.length; i++) {
if (used[i]) {
continue;
}
used[i] = true;
output.push(input[i]);
doPermute(input, output, used, size, level);
used[i] = false;
output.pop();
}
}
return {
getPermutations: function(input, size) {
var chars = input.split('');
var output = [];
var used = new Array(chars.length);
doPermute(chars, output, used, size, 0);
return results;
}
}
})();
for more information, visit http://jinwolf.tumblr.com/post/26476479113/draw-something-cheat
for an working example, check this jsfiddle http://jsfiddle.net/jinwolf/Ek4N5/31/
alert(newString);
newString is not defined right there. Instead, you should use the argument passed:
alert(searchTerm);
Edit: I'm not entirely sure of your approach. It seems overly complicated. This seems to work. I understand that you rather have your own code working, but perhaps this helps you in solving. I don't quite get your substr part.
http://jsfiddle.net/NUG2A/2/
var alphabet = "abc"; // shortened to save time
function permute(text) {
if(text.length === 3) { // if length is 3, combination is valid; alert
console.log(text); // or alert
} else {
var newalphabet = alphabet.split("").filter(function(v) {
return text.indexOf(v) === -1;
}); // construct a new alphabet of characters that are not used yet
// because each letter may only occur once in each combination
for(var i = 0; i < newalphabet.length; i++) {
permute(text + newalphabet[i]); // call permute with current text + new
// letter from filtered alphabet
}
}
}
permute("");
This will result in the following being called:
permute("");
permute("a");
permute("ab");
permute("abc"); // alert
permute("ac");
permute("acb"); // alert
permute("b");
// ...
I'm not sure from your question that you mean "permutations" because usually permutations do not include repeated elements where it looks like you want to include "aaa".
Here are several algorithms for listing permutations you can go check out. If it turns out you mean to have repetitions, it looks like pimvdb has you covered.
Edit: So you know what you are getting into run-time wise:
With repetition (aaa,aab,...): n^k = 26^3 = 17,576
Without repetition (abc,bac,...): n!/(n-k)! = 26!/(26-3)! = 15,600
for (j=0; j < 26;j++){
should be
for (var j=0; j<26; j++) {
Without the declaration, j is a global variable, so it only takes one iteration to get to 26 and then all the loops terminate.
For permutations a recursive algorith as pimvd showed is always nice but don't forget you can just brute force it with for-loops when N is small:
for(int x1=0; x1 < 26; x1++)
for(int x2=0; x2 < 26; x2++)
for(int x3=0; x3 < 26; x3++){
//do something with x1, x2, x3
}
In C#:
void DoPermuation(string s)
{
var pool = new HashSet<string>();
//Permute("", , pool);
pool = Permute(new List<char>(s));
int i = 0;
foreach (var item in pool) Console.WriteLine("{0:D2}: {1}", ++i, item);
}
HashSet<string> Permute(List<char> range)
{
if (range.Count == 1) return new HashSet<string>(new string[] { range[0].ToString() });
var pool = new HashSet<string>();
foreach (var c in range)
{
var list = new List<char>(range);
list.Remove(c);
foreach (var item in Permute(list)) pool.Add(c + item);
}
return pool;
}

Categories