Reputation: 21150
I'm pulling my hair out over this one. I have two arrays, likes
& dislikes
, both filled with about 50 strings each.
I also have a JSON object, data.results
, which contains about 50 objects, each with an _id
parameter.
I'm trying to check find all the objects within data.results
that aren't in both likes
and dislikes
.
Here's my code at present:
var newResults = []
for(var i = 0; i<data.results.length; i++){
for(var x = 0; x<likes.length; x++){
if(!(data.results[i]._id == likes[x])){
for(var y = 0; y<dislikes.length; y++){
if(!(data.results[i]._id == dislikes[y])){
newResults.push(data.results[i]);
console.log("pushed " + data.results[i]._id);
}
else
{
console.log("They already HATE " + data.results[i]._id + " foo!"); //temp
}
}
}
else
{
console.log(data.results[i]._id + " is already liked!"); //temp
}
}
}
As you can see, I'm iterating through all the data.results
objects. Then I check whether their _id
is in likes
. If it isn't, I check whether it's in dislikes
. Then if it still isn't, I push it to newResults
.
As you might expect by looking at it, this code currently pushes the result into my array once for each iteration, so i end up with a massive array of like 600 objects.
What's the good, simple way to achieve this?
Upvotes: 1
Views: 89
Reputation: 8611
When checking whether an Array contains an element, Array.prototype.indexOf
(which is ECMAScript 5, but shimmable for older browsers), comes in handy.
Even more when combined with the bitwise NOT operator ~
and a cast to a Boolean !
Lets take a look how this could work.
Array.prototype.indexOf
returns -1 if an Element is not found.
Applying a ~
to -1 gives us 0
, applying an !
to a 0
gives us true
.
So !~[...].indexOf (var)
gives us a Boolean represantation, of whether an Element is NOT in an Array. The other way round !!~[...].indexOf (var)
would yield true if an Element was found.
Let's wrap this logic in a contains function, to simply reuse it.
function contains (array,element) {
return !!~array.indexOf (element);
}
Now we only need an logical AND &&
to combine the output, of your 2 arrays, passed to the contains function.
var likes = ["a","b","f"] //your likes
var dislikes = ["c","g","h"] //your dislikes
var result = ["a","c","d","e","f"]; //the result containing the strings
var newresult = []; //the new result you want the strings which are NOT in likes or dislikes, being pushed to
for (var i = 0,j;j=result[i++];) //iterate over the results array
if (!contains(likes,j) && !contains (dislikes,j)) //check if it is NOT in likes AND NOT in dislikes
newresult.push (j) //if so, push it to the newresult array.
console.log (newresult) // ["d","e"]
Here is a Fiddle
Edit notes:
1. Added an contains function, as @Scott suggested
Upvotes: 1
Reputation:
Try first creating an array of common strings between likes
and dislikes
var commonStrAry=[];
for(var i = 0; i<likes.length; i++){
for(var j=0; j<dislikes.length; j++){
if(likes[i] === dislikes[j]){
commonStrAry.push(likes[i] );
}
}
}
then you can use this to check against data.results and just remove the elements that don't match.
Upvotes: 0
Reputation: 670
for (var i = 0; i < data.results.length; i++) {
isInLiked = (likes.indexOf(data.results[i]) > -1);
isInHated = (dislikes.indexOf(data.results[i]) > -1);
if (!isInLiked && !isInHated) {
etc...
}
}
Upvotes: 3
Reputation: 725
Use likes.indexOf(data.results[i]._id) and dislikes.indexOf(data.results[i]._id).
if (likes.indexOf(data.results[i]._id) != -1)
{
// they like it :D
}
Upvotes: 0