Multiple select list value interating an extra time in javascript - javascript

I have a multiple select list item with id "genres". In my code, I get the value of "genres", split it, and then iterate through and adds each value to another array. But for some reason, it's adding an extra entry. Here's my code:
if ($("#genres").val()!=null) {
var genres = $("#genres").val().toString().split(",");
for (var i in genres) {
model.TitleGenres.push({ GenreId: genres[i] });
}
}
The variable model.TitleGenres is initialized as [];
When I debug this in Firebug, the values I get are:
genres: [ "6", "1770" ]
At the end of the loop, I get:
model.TitleGenres: [Object { GenreId="6"}, Object { GenreId="1770"}, Object { GenreId=function()}]
I have no idea why there is an extra entry with GenreId=function(), can anybody explain why that is and how to eliminate it?

Do not iterate over (numerical indexed) arrays in JS with for in.
Use for (var i = 0, len = array.length; i < len; i++) { ... }

Its cause you iterate over an array with 'for in' and not foreach or simpley for. With for in you iterate over all members of the array object, or in this case jquery object. It seems that one of them is a function. Use genres.each() instead.

How about this:
var x = [];
$('#genres option:selected').each( function() { x.push($(this).val()) } );
Now "x" will hold all the selected values.

Related

JavaScript remove object from array if value exists in other array

I am using Firebase, so if there is a more efficient way to structure this data in order to be able to query only the cards that have not already been viewed by the logged in user, I am open to going that route as well. Right now I am trying to do the filtering after the fact.
I have an array of all cards included in my application that looks like this:
I have a second array that holds information on all the cards the user has already seen. I want to be able to look through both arrays, and if the cid in Array two matches the $id in Array 1, then remove that object entirely from Array 1.
This is actually very easy to do in a functional way:
array1 = array1.filter(item => array2.every(item2 => item2.cid != item.$id));
Array.prototype.filter() returns, as an array, the elements of an array that cause the supplied function to return true. And our filter-evaluator says 'return true if there is no item in array2 whose CID matches this item's ID'.
Because filter() is returning a new array, there's no need to use splice(); we can just reassign array1 to the newly filtered array.
Loop through the arrays and use splice to remove the element
for(var i =0; i< array2.length; i++ ) {
for(var j= 0; j< array1.length;j++) {
if (array2[i].$id === array1[j].$id) {
array1.splice(j,1);
break;
}
}
Why dont you use one array of objects for that. keep a object key for that
seen
by default keep seen false. and use firebase-query where the column seen is false.
or you can do something like that after fetching the data in your code.
var resultarray = [];
for(var i =0; i< array1.length; i++ ) {
var flag = true;
for(var j= 0; j< array2.length;j++) {
if (array1[1].$id === array2[2].$id) {
flag = false;
break;
}
}
if(flag === true) {
resultarray.push(array1[i]);
}
}

JavaScript returning numeric value instead of string(s) after sorting array

I am working on an exercise where I prompt the user for a list of names, store the list of names in an array, sort the array in ascending order, and print the list of names (one per line). When I do so, I see a numeric value displayed instead of one name per line. Why is this happening?
var namesArray = [];
do {
var names = prompt("Enter a name: ");
namesArray.push(names);
} while (names != "")
namesArray.sort();
for (var name in namesArray) {
document.write(name);
}
When you use this construct:
for (var name in namesArray) {
the value of name will be the index in the array (the property name). If you want the actual value in the array, you have to use that property name/index to get the value:
document.write(namesArray[name]);
Of course, you really should not iterate arrays that way in the first place because that iterates all the enumerable properties of the array object (potentially including non array elements) as you can see in this example. Instead, you should use a traditional for loop as in this code example that follows:
var namesArray = [];
do {
var names = prompt("Enter a name: ");
namesArray.push(names);
} while (names != "")
namesArray.sort();
for (var i = 0; i < namesArray.length; i++) {
document.write(namesArray[i]);
}
Other options for iterating the array:
namesArray.forEach(function(value) {
document.write(value)
});
Or, in ES6, you can use the for/of syntax which does actually work how you were trying to use for/in:
for (let value of namesArray) {
document.write(value);
}
You also may want to understand that using document.write() after the document has already been parsed and loaded will cause the browser to clear the current document and start a new one. I don't know the larger context this code fits in, but that could cause you problems.
First, in a for..in loop, here name represents the keys and not the values in your array (you should use namesArray[name])
Also there is another important thing to note. An array is not recommended to be looped through using for..in and if so, you should do it like this:
for (var key in array) {
if (array.hasOwnProperty(key)) {
// then do stuff with array[key]
}
}
The usual preferred ways to loop through an array are the following:
A plain for loop
for (var i = 0, l = array.length; i < l; i++) {
// array[i]
}
Or a higher order function with Array.prototype.forEach (IE9+ if you need compat with IE)
array.forEach(function (item) {
// do something with the item
});

Removing an object from a javascript list of objects

I currently have a list of objects in javascript indexed by a key:
var list = [];
list['a'] = [];
list['a'].push({obj: 'test'});
list['a'].push({obj: 'test2'});
list['b'] = [];
list['b'].push({obj: 'test'});
list['b'].push({obj: 'test2'});
I would list to remove the entry based on the key (a/b)
I have tried the following:
for(var x in list) { delete list[x]; }
that works but it actually leaves an undefined entry in the list.
I have also tried splicing the array, but that does not seems to work in this case.
Any thoughts on how to remove the entry in javascript or jQuery?
Thanks.
The Fix:
After reading some of the comments, i was able to better understand what my list is consistent of. Therefor, i was able to do the removal by doing the following:
delete list.b;
I'm not sure if my list is best way to organize my structure, but doing a delete on the list and treating it like an object property did the trick.
Thanks for all the feedback.
I'll assume list is an object, not an array.
If you want to reset a or (or b it's done the same way)
list.a.length = 0;
If you want to delete an element from a at a known index (let index)
list.a.splice(index, 1);
You're attempting to add the elements to the array object as object properties and not as array elements. You can verify this by inspecting the value of list.length (will be 0).
So when doing something such as the following:
function removeProperty(id) {
if (list.hasOwnProperty(id)) {
delete list[id];
}
}
removeProperty('a');
it's really the same as:
delete list.a;
which is why you think it leaves an undefined 'entry' in the 'list'.
You'll need to use a literal object instead:
var list = {};
list['a'] = [];
...
list['b' = [];
...
which would allow you to use delete and have it behave as you expect. Of course you'll lose the .length property on the array but you never had that anyway.
Create a simple prototype for the Array class
Array.prototype.remove = function() {
// Helper function to remove a single element from a list if exists
item = arguments[0]
if (this.includes(item)) {
index = this.indexOf(item)
this.splice(index, 1)
}
}
// Now we can call
myList.remove(YourObject)
The above code will add the remove method to all your lists, so this will help you not just for objects but also strings, integers, or any data type
var list = {1: [{},{}], 2: [{},{}]};
function removeProperty(obj, prop){
if(obj[prop]){
delete obj[prop];
}
}
removeProperty(list,"1");
console.log(list);
If this quote:
I would list to remove the entry based on the key (a/b)
means you would like to select the list to consider based off the key (a/b), then remove elements in the list (or all of them), you can try this:
var list = [];
list['a'] = [];
list['a'].push({obj: 'test4'});
list['a'].push({obj: 'test5'});
list['b'] = [];
list['b'].push({obj: 'test'});
list['b'].push({obj: 'test2'});
var toRemove = 'test4';
var removeFrom = "a";
var consideredList;
for (var prop in list) {
if (prop == removeFrom) {
consideredList = list[prop];
}
}
//Remove everything from the considered list
consideredList.splice(0, consideredList.length);
//Remove based off value, if you know the property name
// for(var pos in consideredList) {
// if(consideredList[pos].obj == toRemove) {
// consideredList.splice(pos, 1);
// }
// }
I made a Plunker of a few different cases (check the script.js file). There seems to be a bit of confusion on what you are after and hopefully this is helpful to you somehow. Good luck.

get index of element in array if it exists in another array/object

There are two arrays:
itemKeys: [
{
name: "REFOBJTYPE"
},
{
name: "REFOBJKEY"
}
...
]
itemValues: [
{
value: ""
},
{
value: ""
}
]
and an object
ref: {
REFOBJTYPE: 1,
REFOBJKEY: 2,
}
They are fixed and the structure itself cannot be changed.
values of itemValues should be filled with values from ref object,
to get index we have to look up the itemKeys array.
The point of this question: I don't want to use 2 "for" loops to check for each key if it exists in ref. I WANT use JAVASCRIPT specific features like maybe "indexOf", so:
is the ANY OTHER way, rather than TWO FOR-LOOPs to complete this task?
Please don't question why I need this, why don't I like 2 loops. Obviously under any implementation "behind" it will be 2 loops.
I'm not sure if this is what you meant, but if you loop over the itemKeys array, you can easily look up the value associated with the key in the ref object, and then write that out to the itemValues array in one loop.
for (var i = 0; i < itemKeys.length; i++) {
var key = itemKeys[i].name;
var value = ref[key];
itemValues[i].value = value;
}

Javascript for..in on object property

I have the following JSON:
{"data":[{"id":1,"client_id":1},{"id":2,"client_id":1}]}
I'm trying to do a for...in but something is not going well.
Look at my code:
for (post in data) {
console.log(post.client_id); //return undefined
}
But if I do this:
for (i=0 ; i<data.length; i++) {
console.log(data[i].client_id); //return the correct value
}
Why can't I iterate with for..in in this case?
The value of the "data" property is an array. You need:
for (var i = 0; i < json.data.length; ++i)
console.log(json.data[i].client_id);
That's assuming that the JSON has been parsed and stored in a variable called "json". If it's actually called "data", then it'd be "data.data" instead of "json.data".
You really should not use for ... in loops for real arrays. It's a bad habit for a variety of reasons. Use a numeric index or something like the .forEach() facilities available in newer browsers.
First off, you should NEVER iterate arrays with for/in. That structure iterates properties of the object. You will get all the array elements, but you may also get other iterable properties of the object too.
Arrays should always be iterated with a traditional for loop as in:
for (var i = 0; i < arr.length; i++).
Second off, you have to make sure you're following your own data structure properly. You have this:
var item = {"data":[{"id":1,"client_id":1},{"id":2,"client_id":1}]};
which spread out some more looks like this:
var item = {
"data":[
{"id":1,"client_id":1},
{"id":2,"client_id":1}
]
};
So, your JSON is an object. That object has one property in it called data and that one property's value is an array, which contains objects. You would get the first item in the array with this:
item.data[0]
Or the properties on that object with this:
item.data[0].id
item.data[0].client_id
You would iterate all the items in that array like this:
for (var i = 0; i < item.data.length; i++) {
// access each object in the array
item.data[i].id
item.data[i].client_id
}
it should be like this:
for (var post in data) {
console.log(data[post].client_id); //return undefined
}
this is the correct form to iterate using for... in
for (post in data) {
console.log(post.client_id); //return undefined
}
you're doing this wrong, try it like this:
for (post in data) {
console.log(data[post].client_id); //return undefined
}
you should actually also include a filter, since stuff from the prototype can leak in:
for (post in data) {
if (data.hasOwnProperty(post)) {
console.log(data[post].client_id); //return undefined
}
}
It's because of the structure of your JSON. Notice that you've got an outer object with only a single top-level property: data.
{ "data":
[
{"id":1,"client_id":1},
{"id":2,"client_id":1}
]
}
data doesn't have a client_id property: it's an array of the sub-entries that you're trying to iterate over, and those have client_id properties. This is why your loop that indexes data works.

Categories

Resources