Angular Js stuck in inserting the array values after sorting - javascript

Hello guys i am stuck in angular js.
What i have to do is to show the steps of selectionSort and the code i made is
var myApp = angular.module('myApp',[]);
var arraymain = [];
myApp.controller('myController',function($scope) {
$scope.array2 = [];
$scope.selectionSort = function(list) {
n=list.length;
temp2 = list;
for(i=0; i<n-1; i++) { //need to do n-2 passes
i_min=i;
//finding mining index
for(j=i+1;j<n;j++){//ith position: elements from i till n-1 candidates
if(temp2[j]<temp2[i_min])
i_min=j; //update the index of minimim element
}
temp=temp2[i];
temp2[i]=temp2[i_min];
temp2[i_min]=temp;
alert(temp); //It shows as needed
$scope.array2.push(temp2); //Here i am having problem it saves the sorted final array i.e the last every time of loop but i want to save current array on every outer loop execution
}
return list;
$scope.selectionSort([3,2,3,4,5,1,2]);
console.log($scope.array2[0]);
console.log($scope.array2[1]);
console.log($scope.array2[2]);
});
Sorry for my bad English.

It's not clear what you need to do. I'm pretty sure you've got a real mess on your hands beyond your main problem, and using Angular is only making it worse.
If your goal is to console.log the state of the array at each step of the selectionSort outer loop, then you need to run console.log at the bottom of each loop.
The first thing that looks fishy suspicious is:
$scope.array2.push(temp2);
If you run console.log(array2) at each step of the loop as I suggested, you need this line to be instead:
$scope.array2 = temp2;
That way, you overwrite array2, which holds the state of the array at each iteration of the for loop. Then you log it. Appending each state to a larger array, and then running console.log on each item in that array is not the best way to do this.
But, I'm not sure that's what your problem is.

Related

Checking for existing array in array before pushing

I missing something when trying to push to an array while preventing duplicates.
I keep figuring out code that will push every occurence of an employee to the new employees array but I cannot figure out how to only push an unique list.
My final array is a 2d array so that can be setValues() back into a column in the Google sheet.
function queryEmployees(){
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var lRow = sh.getLastRow();
var data = sh.getRange(1,1,lRow,2).getValues();
var employees = [];
for(i=0;i<data.length;i++){
if(data[i][0]==='Team member evaluated'){
if(employees.indexOf([data[i][1]])===-1){
employees.push([data[i][1]]);
}
}
}
Logger.log(employees);
Logger.log(employees.length);
SpreadsheetApp.getActiveSpreadsheet().getSheets()[1]
.getRange(1,1,employees.length,1).setValues(employees);
}
IndexOf does not work with objects in arrays without your rewriting the function or writing your own. It works fine with strings, though. So a simple fix is to create a parallel array of strings, which allows us to keep your code almost intact. Thus, add,
var employeesIndex=[];
after your
var employees=[]
change the condition on your inner "if" clause to
(employeesIndex.indexOf(data[i][1])===-1)
and within that if block add a line to update the index
employeesIndex.push(data[i][1]);
That way the index tracks duplicates for you while your employees array contains arrays like you need.

Problems with code listing unique items in a list and copying them into new worksheet

I'm trying to run the following code on a spreadsheet. The column of names is the 4th column. I'm attempting to run through that list of names, pushing each new unique name to an array (listOfNames), and then add a new worksheet (NamesList), and finally add the array to cell A1 of the new worksheet. When I run the code below, all I get is a blank popup with an OK and Cancel button. When I view the log, it is blank as well. I'm quite new at this, and I feel like I'm missing something obvious... just not sure what it is. Am I misunderstanding something specific to GAS rather than JS?
var sheet = SpreadsheetApp.getActiveSheet();
var listOfNames = new Array ();
function copyNames() {
var data = sheet.getDataRange().getValues();
for (i=0; i<=sheet.getLastRow(); i++){
var tempName = sheet.getDataRange(i,4).getValue();
for (i=0; i<=listOfNames.length; i++){
if (tempName != listOfNames[i]){
listOfNames.push(tempName);
logger.log(listOfNames);
}
}
}
sheet.insertSheet(ListOfEDs);
sheet.getRange('a1').setValue(listOfEDs);
}
Edit: I'm starting to see that this will push values multiple times to the list... so maybe it's just back to the drawing board all together. I have found other code that would create a list of unique elements, but wasn't really sure how that code worked. I thought I'd try to figure it out myself so I'd at least understand it.
EDIT 2: Ok... I tried some new code, but I'm still getting a blank message box, and nothing on the log. I wasn't sure if having i be the iterator for a for loop within a for loop was a bad thing, so I switched it to j. Also, I know there's the remove duplicates example, and have been looking at that, but am unsure why one needs to use join.
function copyNames() {
var sheet = SpreadsheetApp.getActiveSheet();
var listOfNames = new Array ();
var data = sheet.getDataRange().getValues();
for (i=2; i<=data.length; i++){ //starting at 2 because first row is a header
var tempName = data[i][4];
for (j=0; j<=listOfNames.length+1; j++){
if (tempName != listOfNames[j]){
listOfNames.push(tempName);
logger.log(listOfNames);
}
}
}
sheet.insertSheet("ListOfNames");
sheet.getRange('a1').setValue(listOfNames);
}
As far as I understand you went help instead of a ready solution, so here you go.
First:
Try to avoid using global variables. Keep all your variables inside of your functions. Otherwise you will have issues when you add more functions to your spreadsheet. Your Code should start like this:
function copyNames() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var listOfNames = new Array ();
Second:
Try to decrease the amount of service calls to spreadsheet. it takes several seconds for your script to go to your sheet and take the values. Instead of doing it each time, take these values once and push them in to a variable.
In your case, you already did that, however did not use that variable and kept using service calls. Check this line:
var data = sheet.getDataRange().getValues();
Now all of the data on that sheet is in a variable called data.
sheet.getDataRange(i,4).getValue();
is the same as
data[i][4];
The only difference is that in the first case it will take approximately 2 seconds to get that value, while in the second case only a few milliseconds.
Same goes for
sheet.getLastRow();
Either call it once and push it into a variable and use that, or in your case just use
data.length;
Third:
listOfNames is an empty array, so it's length is 0.
This line
for (i=0; i<=listOfNames.length; i++)
will not even run, as both i and listOfNames.length is 0.
That is why you logger does not give any output. Your script never get's to that line.
Fourth:
You do not have a variable called ListOfEDs, therefore your last two rows of code just give an error. Your script does not know what is ListOfEDs as it doesn't exist.
Hope this helps.

How do you selectively remove models from a Backbone collection and from the server?

For example, if you want to remove the completed todos from a todo list.
Selectively removing models from a Backbone collection and server seems like a common task. What are the common ways to do it, and what are the costs and benefits associated with each way?
Solution One
var toRemove = collection.filter(function(model) {
return condition(model);
});
_.invoke(toRemove, 'destroy');
This seems like the cleanest way. It's what Addy used in his book to delete completed todos (which is a big reason why I list this solution first). It's especially clean if you're reusing the filter function (like he is).
However, I think it's slower than Solution Two because it involves iteration over collection and toRemove, whereas Solution Two only involves iteration over collection. Still, they both have linear run times so it's not too big a deal.
Solution Two
for (var i = collection.models.length-1; i >= 0; i--) { // looping from back to front
var model = collection.models[i];
if (condition(model)) model.destroy();
}
I think this is relatively clean. And as mentioned above, this has the benefit of only having to loop through the collection, not the collection + a filtered version of the collection.
It's important that you loop from back to front. Consider what happens when you loop from front to back:
for (var i = 0; i < collection.models.length; i++) { // looping from front to back
var model = this.models[i];
if (condition(model)) {
model.destroy();
i--;
}
}
When you destroy a model, the models in collection.models basically get shifted up by one. This has two implications:
The length of the array decreases by one.
Say you delete element two. The next element will be four, not three. The index gets incremented to 3, and since the models get shifted up by one, three has an index of 2 and four has an index of 3.
Solutions:
Calculate collection.models.length after each iteration of the loop. Ie. for (var i = 0; i < **collection.models.length**; i++)
Decrement i after you destroy a model.
You could loop from front to back, but you would just have to address these things, which makes it a bit more complicated.
Solution Three
var toRemove = [];
collection.forEach(function(model) {
if (condition(model)) toRemove.push(model);
});
toRemove.forEach(function(model) {
model.destroy();
});
This is pretty similar to Solution One.
Differences:
We're using a forEach to construct toRemove instead of filter.
We're manually iterating through and calling destroy instead of using invoke.
Like Solution One, you have to iterate through collection and through toRemove, and so it presumably takes longer than Solution Two.
Note: we can't destroy the model in the first forEach loop. If we do, then it has the same problem as the front-to-back loop in Solution Two. To get around this limitation, we have to use the toRemove array.
Solution Four
This uses reset() + the reset event.
var toKeep = collection.filter(function(model) {
return condition(model);
});
collection.reset(toKeep);
and
collection.on('reset', function(after, before) {
// let after.length = k
// let before.length = n
after.sort(); // k*logk
for (var i = before.length-1; i >= 0; i--) { // n
var model = before[i];
if (!binarySearch(model, after)) model.remove(); // logk
}
// total runtime: n*logk + k*logk
});
This seems a bit excessive to me, but is an option.

How can I push a null value into the start of an array?

I have this code that fetches data and puts it into an array:
this.$httpGetTest(this.test.testId)
.success(function (data: ITestQuestion[]) {
self.test.qs = data;
});
It works and populates the array starting with self.test.qs[0].
However many times my code references this array (which contains a list of questions 1...x)
I must always remember to subract 1 from the question number and so my code does not look clear. Is there a way that I could place an entry ahead of all the others in the array so that:
self.test.qs[0] is null
self.test.qs[1] references the first real data for question number 1.
Ideally I would like to do this by putting something after the self.test.qs = and before data.
Push values at start of array via unshift
self.test.qs.unshift(null);
You need to use Splice(), It works like:
The splice() method changes the content of an array, adding new elements while removing old elements.
so try:
self.test.qs.splice(0, 0, null);
Here mid argument 0 is to set no elements to remove from array so it will insert null at zero and move all other elements.
Here is demo:
var arr = [];
arr[0] = "Hello";
arr[1] = "Friend";
alert(arr.join());
arr.splice(1,0,"my");
alert(arr.join());
You can start off with an array with a null value in it, then concat the questions array to it.
var arr = [null];
arr = arr.concat(data);
You could do something like:
x = [null].concat([1, 2, 3]);
Though there isn't anything wrong with doing something like:
x[index-1]
I'd prefer it to be honest, otherwise someone might assume that the index value returned is 0 based.

Javascript resetting an array

I'm having with some very strange behaviour when I try to reset an array; eg:
data.length=0;
where data is an array. I'll try and include only the relevant code here but basically what I;m doing is on each iteration of my program I'm populating the array with updated values and the array then is used in another function. But when I reset the array the function appears to get the values on the first iteration but none afterwards.
However when I don't reset the array then the function gets the values, but also the older values. I don't want this, as I only want the new updated values only. This is a code snippet:
var buffer = [['1',[0]],['2',[0]],['3',[0]],['4',[0]]];
var dataset = [];
ws.onmessage = function(evt){
dataset.length=0;
var distances = JSON.parse(evt.data);
console.log(distances);
for(var i=0; i<buffer.length; i++) {
if(buffer[i][0] == distances.miles) {
buffer[i][1][0]++;
}
//console.log(buffer);
dataset.push(buffer[i][1][0]);
draw();
//console.log(dataset);
}
}
The function uses the dataset array to redraw a chart.
I've tried to keep it simple here, but the full function is here.
I really don't know what's causing this unexpected behaviour.
EDIT:
console.log(dataset) shows the new updated values, but somehow dataset.length=0; is preventing the updated array to be used by the draw() function. As without the resetting of the array the array can be used by the draw() function.
EDIT:
I've tried to not reset the array but instead get the last 4 elements and put them in a new array and then send them to the draw(), but still the same odd behaviour:
x = dataset.slice(-4);
console.log(x);
draw();
But if I don't do that or don't clear the array, then draw() render a 'wrong' chart. I can't see what is wrong.
THE problem somehow seems to reside with the resetting of the array and that because of this it means the draw() function appears to be called only once at the first iteration.
Please, Please help
You don't need to set length at all. To clear a list of all value, just set it to an empty list:
dataset = [];
Looking at your code, I'm not sure, but why do you even have dataset? You don't ever read anything out of it, and you say you want to clear it every time thru the array.
Do you mean do to something like:
for(var i=0; i<buffer.length; i++) {
if(buffer[i][0] == distances.miles) {
buffer[i][1][0]++;
}
dataset.push(buffer[i][1][0]);
}
draw(dataset); // draw outside the loop, using dataset.

Categories