Javascript conditional callbacks - javascript

I'm currently using javascript to do some experiments and although I'm not new to JS I have a doubt that I hope the good folks at SO will be able to help.
Basically I'm making a jsonp request to a webservice that returns me the amount/length on the reply (just counting objects).
Then I'm randomly selecting 9 of those objects to place in an array and here lies the problem. I would like to make sure that none of those 9 objects is repeated.
To achieve this I'm using the following code:
function randomizer() {
return Math.ceil(Math.random()*badges.length);
}
function dupsVerify(array, number) {
array.forEach(function () {
if(array === number) {
return true;
}
});
return false;
}
// Randomly choose 9 array indexes
var randomBadge = function () {
var selectedIndexes = new Array();
while(selectedIndexes.length < 9) {
var found = false;
var randomNumber = randomizer();
if(!dupsVerify(selectedIndexes, randomNumber)) {
selectedIndexes.push(randomNumber);
} else {
newRandom = randomizer();
dupsVerify(selectedIndexes, newRandom);
}
}
return selectedIndexes;
}
I've tried a couple different methods of doing this verification but I've been thinking if it wouldn't be possible to do the following:
Generate the random number and go through the array to verify if it already exists in the array. If it exists, generate another random number (randomize call) and verify again.. If it doesn't exist in the array, then push it to the "final" array.
How can I achieve this? Using callbacks?
Am I doing this right or should I chance the code? Is there a simpler way of doing this?
Best Regards,

This would get you the desired behavior:
function getRandomPositions(sourcearray, desiredcount){
var result = [];
while(result.lentgth < desiredcount){
var rnd = Math.ceil(Math.random()*sourcearray.length);
if (result.indexOf(rnd) == -1){
result.push(rnd);
}
}
return result;
}
Instead of generating X random numbers, just generate a random number, but don't add it if it already exists.

I ended up finding the best solution for this scenario by using the following code:
function randomizer() {
return Math.ceil(Math.random()*badges.length);
}
function dupsVerify(array, number) {
var result;
if(array.length === 0) {result = false;}
array.forEach(function (item) {
if(item === number) {
result = true;
} else {
result = false;
}
});
return result;
}
// Randomly choose 9 array indexes
function randomBadge() {
while(cards.length < 9) {
var randomNumber = randomizer();
if(!dupsVerify(cards, randomNumber)) {
cards.push(randomNumber);
} else {
randomBadge();
}
}
return cards;
}
This represents the same behavior (and a few minor code corrections) but ensures that I will never get an array with 2 repeated objects.

Related

Sort method for an objects property that is inside an array of objects from a class

I need help with my sort() method from inside the AddressBook class. I tried to figure it out on my own from examples on stackoverflow but I can't seem to get it to work since most of the examples don't involve working from a class instance. If you could please look at the sort() method and let me know where I am going wrong. I think i need to loop through somehow and then reposition the array order.
window.onload = init;
let abm;
function init() {
abm = new AddressBook();
}
class Contact {
constructor(name, email) {
this.name = name;
this.email = email;
}
}
//DO NOT MODIFY ABOVE THIS LINE
function formSubmitted() {
event.preventDefault();
var user = document.getElementById("name").value;
var mail = document.getElementById("email").value;
var newContact = new Contact(user, mail);
abm.add(newContact);
abm.display();
}
function sortList() {
//CODE HERE ONLY
abm.sort();
abm.display();
}
class AddressBook {
constructor() {
this.contactList = [];
}
add(contact) {
//CODE HERE ONLY
this.contactList.push(contact);
}
display(htmlId) {
//CODE HERE ONLY
var html = "<table border='1|1'>";
for (var i = 0; i < this.contactList.length; i++){
html+="<tr>";
html+="<td>"+this.contactList[i].name+"</td>";
html+="<td>"+this.contactList[i].email+"</td>";
html+="</tr>";
}
html+="</table>";
document.getElementById("contacts").innerHTML = html;
}
sort() {
//CODE HERE ONLY
for (var i = 0; i < this.contactList.length; i++){
var tA = this.contactList[i].name.toUpperCase();
var tB = this.contactList[i].name.toUpperCase();
if (tA < tB) {
return -1;
}
if (tA > tB) {
return 1;
}
return 0;
}
}
}
this.contactList.sort((a, b) => a.name.toUpperCase() - b.name.toUpperCase());
You can learn more at Mozilla Developers
I assume you want to sort this.contactList in-place.
Note that you do not perform any assignment to this.contactList in your sort() code. This is the first bug.
The second bug is that you return a value from the function immediately, instead of sorting your data.
The third bug is, that you cannot sort in O(N) complexity (i.e. with a single pass on the data).
You need to decide which sorting algorithm you want to implement, or use the the native javascript implementation which is MergeSort.
In this case, you'd need to pass a function to express how and using which properties you want to sort your data, which is kind of what you tried to do, using -1, 1, and 0.
In this case, you can implement sort() in the following way:
sort() {
this.contactList = this.contactList.sort(function(a, b) {
var tA = this.contactList[i].name.toUpperCase();
var tB = this.contactList[i].name.toUpperCase();
if (tA < tB) {
return -1;
}
else if (tA > tB) {
return 1;
}
return 0;
}
}
Or in an equivalent way (make sure you understand why it's equivalent):
sort() {
this.contactList = this.contactList.sort(function(a, b) {
return a.name.toUpperCase() - b.name.toUpperCase();
}
}

how to itereate an json object in angularjs using for loop?

I have one array i want to iterate that in the iteration process we check one condition if condition is true we return one value otherwise we return else part I write some code but its not working.
the loop will not terminated if condition is true how can i do that cam anyone help me?
$scope.bgImages = []; //it having some objects
$scope.job = []; //it also having some objeccts
//if both elements are matching we return one value
$scope.getJobDepartmentImg = function() {
var jobDepartment = $scope.job.department;
for (var i in $scope.bgImages) {
var department = $scope.bgImages[i].departmentName;
var job_header = $scope.bgImages[i].s3ImageUrl;
if (jobDepartment === department) {
return job_header;
} else {
return default_job_header;
}
}
};
The loop is not terminated if condition is satisfiedd that method will continiouslyy can anyone help me?
put an second return outside else statement
$scope.getJobDepartmentImg = function() {
var jobDepartment = $scope.job.department;
for (var i in $scope.bgImages) {
var department = $scope.bgImages[i].departmentName;
var job_header = $scope.bgImages[i].s3ImageUrl;
if(jobDepartment === department){
return job_header;
}
}
return default_job_header;
}
it will iterate through array and return job_header if it finds one, or return default if loop ends

Array objects difference javascript angularjs

I have 2 array objects and I want to get the difference between them as follows:
array1 = [{"name":"MPCC","id":"tool:mpcc"}, {"name":"APP","id":"tool:app"}, {"name":"AII","id":"tool:aii"}, {"name":"VZZ","id":"tool:vzz"}, {"name":"USU","id":"tool:usu"}]
array2 = [{"name":"APP","id":"tool:app"}, {"name":"USU","id":"tool:usu"}]
result = [{"name":"MPCC","id":"tool:mpcc"}, {"name":"AII","id":"tool:aii"}, {"name":"VZZ","id":"tool:vzz"}]
Here is the code:
$scope.initial = function(base, userData){
var result = [];
angular.forEach( base, function(baseItem) {
angular.forEach( userData, function( userItem ) {
if ( baseItem.id !== userItem.id ) {
if (result.indexOf(baseItem) < 0) {
result.push(baseItem);
}
}
});
});
return result;
}
$scope.initial(array1, array2);
The problem with the above code is I dont get the desired result. Please let me know what is going wrong.
That is not related to Angular.
You could do something like this:
var result = array1.filter(function(item1) {
for (var i in array2) {
if (item1.id === array2[i].id) { return false; }
};
return true;
});
Or with ES6 syntax:
var result = array1.filter(i1 => !array2.some(i2 => i1.id === i2.id));
I think this is not related to Angular itself. You're looking for an algorithm to compute a difference between 2 sets.
The topic has already been discussed. You may also be interested on this underscore plugin

Underscore reject Function with IndexOf removes all objects from array

I have a small Angular app that I'm writing that makes use of Underscore to look over each object in an array, and remove the object if it does not match the keyword (user input).
$scope.search = function() {
$scope.posts = _.reject($scope.posts, function(p) {
var i = 0;
if ($scope.keywords.indexOf(p.author) < 0 ) {
i++;
}
if ($scope.keywords.indexOf(p.id) < 0 ) {
i++;
}
if(i > 0) {
return true;
}
});
};
As you can see I'm setting a counter, and then adding to the counter if the keyword is found in the index, then at the end checking the counter to return true or false to remove the object from the array. $scope.posts is array of objects with my data and $scope.keywords is the user input. I'm wanting to lookup the input from $scope.posts.author object and $scope.posts.id object.
If I remove one of the if statements the function performs as expected: everything not matching the keyword is removed from the array. However, as soon as I add another if statement to the function (as seen in my example above), ALL objects are removed from the array.
It looks to me as though filter might be a better fit here:
$scope.posts = _.filter($scope.posts, function(p) {
return $scope.keywords.indexOf(p.author) > -1 || $scope.keywords.indexOf(p.id) > -1;
});
Working example: http://jsfiddle.net/4xp3sm10/
Instead of filter or reject it would be even easier to do it the opposite way using _.where
var newArray = _.where($scope.posts, {keyword : $scope.keyword});
There you go, one line.
Edit:
If you are stuck on doing it this way, here's a way you could clean it up a little.
$scope.posts = _.reject($scope.posts, function(p) {
var check = false;
if ($scope.keywords.indexOf(p.author) < 0 ) {
check = true;
}
if ($scope.keywords.indexOf(p.id) < 0 ) {
check = true;
}
if(i > 0) {
return check;
}
});
};
No need to use an integer like that
Since you are rejecting rows you will want to make sure ALL conditions are true. Your code is just checking for either one to be true.
$scope.search = function() {
$scope.posts = _.reject($scope.posts, function(p) {
return (
($scope.keywords.indexOf(p.author) < 0 ) &&
($scope.keywords.indexOf(p.id) < 0 )
);
});
};

Iterate a function until result from called function is equal, javascript

I need to iterate a function several times until it returns same thing twice.
This needs to go into a for-loop somehow but I can't get my head around how to this. Here's some code with 4 manual iterations. Any ideas how to put this in a for-loop?
Velocity.prototype.removeCombinedDistancesThatAreShorterThanTrainLength = function(wayPoints, lengthOfTrain){
var firstTry = this.removeWayPointsWhichAreShorterThenTrainLength(wayPoints, lengthOfTrain);
var secondTry = this.removeWayPointsWhichAreShorterThenTrainLength(firstTry, lengthOfTrain);
if(firstTry === secondTry){
return firstTry;
}else{
var thirdTry = this.removeWayPointsWhichAreShorterThenTrainLength(secondTry, lengthOfTrain);
if(thirdTry === secondTry){
return secondTry
}else{
var forthTry = this.removeWayPointsWhichAreShorterThenTrainLength(thirdTry, lengthOfTrain);
if(thirdTry === forthTry){
return forthTry
}
}
}
return forthTry;
};
Something like this (not tried, but should give you the general idea):
var lastTry = null;
var thisTry = wayPoints;
do
{
lastTry = thisTry;
thisTry = this.removeWayPointsWhichAreShorterThenTrainLength(lastTry, lengthOfTrain);
} while (lastTry !== thisTry);
If it's possible that the result will never become equal, consider implementing a safeguard for this, like a maximum number of iterations.

Categories

Resources