Looping through a List of objects in JavaScript - javascript

I want to loop through the student list which I received from a REST service located on a server. this list contains objects for students enrolled in a section. Each object has firstName, lastName, student ID and many other attributes, specifically an attribute called isAbsent. Its a Boolean value where it has true if the student is absent and false if the student is present in not absent. I want to store the students IDs who are absent (have isAbsent=true) in another String Array.
I tried this :
{
//this array will store the IDs of students who are absent.
$scope.selection = [];
//$scope.studentList is the list of students for CRN=X and Date=Y
for (id in $scope.studentList) {
if ($scope.studentList.isAbsent === true) {
$scope.selection.push($scope.studentList.id);
console.log($scope.selection);
}
}
}
This code doesn't execute. I have no clue why, I guess the problem in the loop structure. Any help?

Maybe this will help?
for (var i=0;i<$scope.studentList.length;i++)
{
if ($scope.studentList[i].isAbsent === true)
{
$scope.selection.push($scope.studentList[i].id);
console.log($scope.selection);
}
}
p.s. don't use for..in with arrays. It will display an index instead of a value. It's not like C#.

Depending on what browsers you need to support (e.g. IE >= 9), I'd suggest the newer foreach construct. I find it easier to use:
$scope.studentList.forEach(function(value, index, array) {
if (value.isAbsent === true)
{
$scope.selection.push(value.id);
console.log($scope.selection);
}
});

Related

Array of arrays of Objects

I have an array that looks like this.
let name
function arrayfunction () {
selling = confirmedSale
testSample = {something:das, something1: dso}
productName = [name, selling ,testSample]
qualifiedProduct = ["Selling", productName]
qualified.push(qualifiedProduct);
}
I want to be able to search by name and do work on that name. However, the challenge I am encountering is that it's a nested array of arrays with an object. I have figured out how to do work on the object via two foreach loops but am unable to delete productName and all related elements when the work is complete.
console logging qualified through each of my sets of creating the array to buying and selling is working great and works as it should. Now, I want to delete the productName and all associated elements to productName from the array of Buying and Selling once I have finished doing work on it.
I am relatively new to programming and any direction would be appreciated!
Use findIndex() to find the index of the product with the name you want to remove.
index = qualified.findIndex(q => q[0] == "Selling" && q[1][0] == "someName");
if (index != -1) {
qualified.splice(index, 1);
}

Filter through Angular Collection fast

I know it's trivial but I have a doubt to be clarified.
I have a collection vm.groups that has almost 1000 objects. Now, each object has name, id, links etc. property fields.
Grid only displays name and id.
Now, there is a text box where we enter some text and we have to filter data, according to whatever we entered but filtering must happen only within name and id fields of the objects not the other fields that are present within the objects.
So, both things can be done,
1) I create a temp collection from the original collection objects with only name and id fields and then bind the collection to view.
// vm.groups.forEach(function(element) {
// vm.displayedFieldGroups.
// push({name: element.name,id: element.id,transformedId: element.transformedId});
// });
2) Or, I create a custom filter vm.customSearch :
vm.customSearch = function(searchVal) {
if(vm.filter.length) {
if(vm.filter.toLowerCase().indexOf(searchVal.name.toLowerCase) !== -1 ||
vm.filter.toLowerCase().indexOf(searchVal.name.toLowerCase) !== -1) {
console.log(searchVal);
return true;
}else {
return false;
}
} else {
console.log(searchVal);
return true;
}
};
And in the view vm.groups | filter: vm.customSearch.
But I think second method is slower because each value in the collection would be passed to the filter which is obviously tedious for huge collection.
Am I right?
Which is the right way to do?
UPDATE
This was for a legacy application. There was a filter already implemented but that just goes through all the fields in the object. I need to only filter for name and id fields of objects.
Hence, I need to either create a custom filter or choose the first approach that I depicted.
You're right in your assumption that the filter would go over every item in the source array and run your filter function each time there's a digest cycle.
You should proceed with the first approach.

Check whether any of multiple values exists in an array

(This question has been changed a bit since some of the answers were posted. That is why they might seem a bit off-topic and/or out of context)
Hello! So basically, I have this string that is entered by a user (a caption for an image, for example), and an array of links/words that I want to "block" the user from entering. (This would be to prevent from swearing, advertising etc.)
So I need some code that checks whether a certain value exists in an array.
This is my array:
var blockedUrls = ["https://google.com", "https://facebook.com"]
and this is the values I want to check
var userInput = "Hello! Check out my cool facebook profile at https://facebook.com";
(This would normally be set to a value fetched from an input of some sort, the static text is just to simplify)
So this is what I have tried:
let values = userInput.split(" ");
values.forEach((i, value) => {
// inArray is a made-up-function in order to better explain my intention
// The function I need here is a function that can check whether the value of the "value" variable exists in the "blockedUrls" array.
if(value.inArray(blockedUrls)) {
return alert(`You can't say that word! [${value}]`);
}
});
So a summary: How do I check if any of multiple values exists in an array?
You can check if a value is in an array by using indexOf
var value = document.getElementById('myFile').value;
if (unAllowedLinks.indexOf(value) != -1) {
// value is in array
}
-1 is returned when the value is not found in the array, else it returns the index of the value.
If you want to be able to change the number of values in unAllowedLinks you’d be better off using indexOf(), like so:
function updateImage() {
if (unAllowedLinks.indexOf(document.getElementById('myFile').value) > -1) {
alert("This link is reserved");
} else {
// Use the value
}
};

Printing individual objects to a DOM when their IDs vary

I am working on a JavaScript web app that takes input from a user (the name of a musical artist) and outputs a list of related artists and their most popular song, as determined by the Spotify API. I initially had a rudimentary version of this functioning, but it would just post a list of all the related artists with a list of those related artists' most popular songs immediately above it, and I want the entire object to print out (artist plus most popular song).
I have a series of objects representing the artists that I received through the spotify-web-api-js node module with Node.js and Browserify to make it function on the browser, uniquely identified by their Spotify ID. How can I loop through them if I don't know those IDs in advance before a user does a search so that I can properly push them into an object that I can then input to the DOM through jQuery's append? I've been trying to access them in various ways, but it doesn't seem to be working:
s.getArtistRelatedArtists(originalArtistId, function(err, data) {
for (i = 0; i < data.artists.length; i++)
{
console.log(data.artists[i].name);
relatedArtistsObject[data.artists[i].id] = {
name: data.artists[i].name,
songs: []
};
s.getArtistTopTracks(data.artists[i].id, "US", function (err, data2) {
if (relatedArtistsObject[data2.tracks[0].artists[0].id] !== undefined)
{
// console.log(data2.tracks[0].name); -- this outputs the song titles I want
relatedArtistsObject[data2.tracks[0].artists[0].id].songs.push(data2.tracks[0].name);
}
});
}
console.log(relatedArtistsObject);
// loop through this object and print it through the screen
for (k = 0; k < relatedArtistsObject.length; k++)
{
console.log(relatedArtistsObject.id.songs[0].name);
$('#related-artist').append(relatedArtistsObject[k]);
}
// $('#related-artist').append(relatedArtistsObject);
});
Here is a link to the full code (not functioning because it doesn't have Node.js/browserify enabled): https://jsfiddle.net/pmh04e99/
This answer is partially helpful, but doesn't apply here because the JSON output doesn't have a "name" field in the array I want to access. Instead, songs is an array of 1, and the content I want is within item 0. My console.log output of the relatedArtistsObject looks like this, for example:
How can I access these objects in the DOM through my code when I don't know the spotify IDs right now?
Note: I'm aware that i'm not error handling yet, but I want to be able to implement the main functionality first.
You can use for in or use Object.keys.
The former will iterate over each enumerable property name of the object, and setting that name into the specified variable. You can then use that name to access that object's property value.
The latter will return an array of the object's property names. You can then use a regular for loop to iterate over that array and use each of the values in the array as the id
For...In
for(id in relatedArtistsObject){
var artist = relatedArtistsObject[id];
console.log(artist.name,artist.songs);
}
Object.keys
var ids = Object.keys(relatedArtistsObject);
for(var i=0; i<ids.length; i++){
var artist = relatedArtistsObject[ids[i]];
console.log(artist.name,artist.songs);
}

Checking for equivelance

OK, I'm missing something here and I just can't seem to find it because the logic seems correct to me, but I'm certain I'm not seeing the error.
var VisibleMarkers = function() {
var filtered = _.reject(Gmaps.map.markers, function(marker) {
return marker.grade != $('.mapDataGrade').val() && !_.contains(marker.subjects,$('.mapDataSubjects').val())
});
return filtered
}
I'm using underscore.js and jQuery to simplify my javascript work.
So right now, I'm checking by means of selects which data gets to be rejected and then I display the filtered markers on the (google) map (if it helps at all, this is using gmaps4rails which is working perfectly fine, its this bit of javascript that's making me lose the last of the hairs on my head).
Currently, the code functions 100% correctly for the ".mapDataGrade" select, but the ".mapDataSubjects" isn't. Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
Can someone see what I'm doing wrong?
If there's more info that needs to be included, please let me know.
This is on plain javascript on a RoR application using gmaps4rails
Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
_.contains compares a values, but it sounds like you want your iterator to compare a value to an object's "id" property. For that, _.some would work; it's like contains, except that, instead of comparing values, you can write the comparison as a function:
Returns true if any of the values in the list pass the iterator truth test.
Here's how you'd use it:
!_.some(marker.subjects, function(subject) {
return subject.id == $('.mapDataSubjects').val();
})
If I'm right, the whole line should be like this:
return marker.grade != $('.mapDataGrade').val() &&
// check that none of the subjects is a match
!_.some(marker.subjects, function(subject) {
// the current subject is a match if its ID matches the selected value
return subject.id == $('.mapDataSubjects').val();
});

Categories