JavaScript remove object from array if value exists in other array - javascript

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]);
}
}

Related

How to work with multidimensional array when the number of dimension is variable?

Hello stackoverflow members.
I come with the following problem:
To start we have
var myArray = [[array1],[array2],[array3],[arrayN],...];
where each array is filled with a known number of strings such as
var array1 = ["a","b"], array2 = ["1","2"], array3=["&","é"];....
and so on.
I'm looking for a method to get this result:
expected result ===> a1&;a1é;a2&;a2é;b1&;b1é;b2&;b2é; ....
If the number of dimension were fixed I could use for loops to iterate and build the result, BUT here the problem is that I want to be able to enter N arrays in the main array myArray and by doing so, I change the depth of the nested loops.
If not do you have some ideas to put me on the track of the solution to this?
Thanks!
EDIT by the way this is what i experimented:
for (i=0; i<myArray[0].length; i++){
for (var j =0; j<myArray[1].length; i++){
for(var k = 0; k<myArray[2].length; k++{
console.log(i+j+k);
}
}
}
BTW i can't find a way to describe a function which would nest N for loops where N is myArray.length + 1 (the number of arrays in myArray).
EDIT: i found an iterative way of doing it and wanted to share the solution:JSFiddle
To get a flat list of all cells, something like the following recursive function should work (if you have a non-empty array of arrays, and all array items are strings):
function makeFlatList(inputArray) {
if (inputArray.length == 1) { // if this array has only one array inside
return inputArray[0]; // return the array inside
} else {
var outArr = [];
var arrayShifted = inputArray.slice(1); // remove first subarray from inputarray
var arrayShiftedFlat = makeFlatList(arrayShifted); // recursive call
for (var i=0; i<inputArray[0].length ; i++) { // loop over first array
for (var j=0; j<arrayShiftedFlat.length; j++) {
outArr.push(inputArray[0][i]+arrayShiftedFlat[j]); // add items to outArr
}
}
return outArr;
}
}
Working JSBin here

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
});

Using 2 arrays of objects, iterate over them using something similar to IndexOf (or other option)

I have an array of objects, i was trying to iterate over. The array is pretty simple in format.
{a:5, b:"key", c:19}
i was trying to compare an array with a subset, say: [{a:5},...]
for (var i = 0; i < subset.length; i++) {
var searchTerm = subset[i].a;
var index = objs.indexOf(searchTerm, function (el) {
return el.a;
});
if (index > -1) {
objs[index].Found = true;
}
}
So that way ultimately objs, could have a new key in it, 'Found'
This way, it will set the main array objs item.Found = true, if it existed in subset.
There are 2 issues though. Accounting for multiple instances of the same item, and the fact that this current implementation doesnt seem to work.
This is a slight expansion of (indexOf method in an object array? )but with an array of search terms.
ideally, i dont want to change the arrays at all, so im trying not to slice, etc.
In a lot of the defintions, indexOf is defined as:
function indexOf (key, start);
instead of the ideas i am trying to work with.
Edit
Here is some code that i have to get this working, but i was thinking there is a more effecient way to do it than written.
for (var j = 0; j < compare.length; j++){
var searchTerm = compare[j]["a"];
for (var k = 0; k < objs.length; k++){
if (!objs[k].Found && objs[k]["a"] == searchTerm){
objs[k].Found = true;
break;
}
}
}

Retrieve Index Number of Unique Elements

for (let i = 0; i < arrayItemsLen; i++) {
let uniqueItems = arrayItems.filter(function(item, i, arrayItems) {
return i == arrayItems.indexOf(item);
});
}
This method retrieves unique items in the arrayItems to uniqueItems array. What I want to do is also get the index numbers of each unique element and assign it to another temp array. I can't find a way to achieve that.
E.g.: arrayItems.indexOf(item) gives the index of each unique element, but then, how do I get that index to the tempArray[i], I guess I need a for loop but I really don't know where to put it.
I would use something like
var uniqueIndices = [],
uniqueValues = [];
for(var i=0; i<array.length; ++i) {
if(uniqueValues.indexOf(array[i]) >= 0) continue;
uniqueIndices.push(i);
uniqueValues.push(array[i]);
}
Basically, it iterates array checking if the current value is already in uniqueValues. If it's there, it does nothing and continues to the next iteration. Otherwise, it adds the value to uniqueValues and the key to uniqueIndices.
Using i == array.indexOf(array[i]) like in your question would also work, but it may be slower because array will be bigger than uniqueValues.

Multiple select list value interating an extra time in 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.

Categories

Resources