JavaScript checking if something is unique in an array - javascript

I've been searching around SO and google but I'm not sure how to go about what I'm doing. I'm creating my own little app that uses ajax and Yahoo API to bring back RSS feed information and display it to the page, it brings back title, description, thumbnail and GUID.
The issue at hand is data returned in the array with an image is duplicated so my idea is "I'll check guids and if they aren't unique remove one" but what I've tried isn't working. Any advice is appreciated!
This is how I'm getting my data, converting xml into JSON which will contain properties "title, description, pubdate, thumbnail & guid"
function getData() {
return $.getJSON("giant yahoo api url" + "%22&format=json&callback=?",
function(data) {
}
);
Duplicate handling
handlebars.registerHelper("removeDuplicate", function(results) {
var a = results;
var b = results.guid;
var i = 2;
foreach(b in a) {
if( b.count != 1) {
b--;
}
}
});

To fix the duplicate issue I was having I've written a handlebars helper as I was doing before but with a couple of tweaks it now works as intended and returns only the [0] item if the item is in an array!
handlebars.registerHelper("rssFeed", function(results) {
var a = results;
if(Array.isArray(a)) {
return a[0];
}
else {
return a;
}
});

You can filter like below:
var uniques = [];
results.forEach(function(result)) {
var control = true;
uniques.forEach(function(single) {
if(single.guid == result.guid) control = false;
if(control) uniques.push(result);
})
}

You could use Array.prototype.reduce, quick (sloppy) example:
handlebars.registerHelper("removeDuplicate", function(results) {
return results.reduce(function(arr, item) {
var unique = true;
arr.forEach(function(i) {
if (i.guid === item.guid) unique = false;
});
if (!unique) return arr;
arr.push(item);
return arr;
}, []);
});

Related

Pushing object to Array makes parameter empty

I'm trying to solve problem of merging two arrays of objects, so I wrote a pretty simple function
function mergeShowtimes(movies) {
var existing_halls = [];
return movies.reduce(function(acc, movie) {
var movies_with_hallid,
movies_seats;
if (existing_halls.indexOf(movie.hallId) === -1) {
movies_with_hallid = _.filter(movies, function(filter_movie) {
return movie.hallId === filter_movie.hallId;
});
movies_seats = _.map(movies_with_hallid, 'seats');
movie.seats = _.union.apply(this, movies_seats);
acc.push(movie);
existing_halls.push(movie.hallId);
}
return acc;
}, []);
}
problem is, whenever I check the value of movie and movie.seats, field 'seats' in movie is empty, but movie.seats is not, for some reason
If I'll remove acc.push(movie); everything will start working as planned
What am I doing wrong?
Thanks for any feedback!

AngularJS 1.x NgTagsInput show message

I have this code using AngularJS and NGTagsInput.
I'm using Filter in AutoComplete, and you can add new itens pressing 'Enter', but i wanted show this message to user. If there is not a result in auto complete, show message: "No results found. Press Enter to Add"
I tried put a Else inside Filter. but does not work because he checks every single letter.
$scope.loadCountries = function($query) {
return $http.get('countries.json', { cache: true}).then(function(response) {
var countries = response.data;
return countries.filter(function(country) {
return country.name.toLowerCase().indexOf($query.toLowerCase()) != -1;
});
});
};
});
Here is a Plnkr: PLUNKR
Thanks for now ! =)
You just need to check if there are a returned item matched, in other way just check if the array filtered with that query has an item. If there are no matched item this mean no data :D
$scope.loadCountries = function($query) {
return $http.get('countries.json', { cache: true}).then(function(response) {
var countries = response.data;
var filtered = countries.filter(function(country) {
return country.name.toLowerCase().indexOf($query.toLowerCase()) != -1;
});
$scope.nodata = filtered.length === 0;
return filtered;
});
};
http://plnkr.co/edit/fo1lExzjz0eJxloaljd0?p=preview

Display certain filtered search results

I have tracks and places being pushed into the search results. I want to only show tracks. The _type of a place is "system.place" and a track is "system.tracking". Even though I have an if statement to check each result from the search it still displays all results. Any input will be helpful.
$scope.trackSearchChanged = function(searchText) {
if (searchText == '') {
$scope.trackSearchResults = [];
}
else {
Service.typeAheadSearch(searchText, 20).then(function (response) {
angular.forEach(response.results, function (track, index) {
if (track._type != "system.place") {
$scope.trackSearchResults = response.results;
}
});
});
}
};
In order for your forEach function to filter anything, you'll have to create a second array to push your desired values into.
Service.typeAheadSearch(searchText, 20).then(function (response) {
var places = [];
angular.forEach(response.results, function (track, index) {
if (track._type != "system.place") {
places.push(track);
}
});
$scope.trackSearchResults = places;
});

How to process users in one specific order using map o each function?

I create a cloud function that process all the items in a specific order and then make a network request to an API for each item and update them with the result of the API.
I tried to do something like this. But the order is not respected and the computation of the "remainingCredits" is wrong.
Note that the function "getUserPageView()" make an API call and return a promise with the result.
query.descending("createdAt");
return query.find().then(function(items) {
var remainingCredits=0;
var promises= _.map(items, function(item){
var credit=item.get("credit_buy");
return getUserPageView(123, new Date()).then(function(pageviews){
var usedCredit=credit-pageviews;
if(remainingCredits>0)
return remainingCredits+credit;
if(credit-usedCredit<=0){
console.log("usedCredit:"+usedCredit);
item.set("used",true);
return 0;
}else{
remainingCredits+=usedCredit;
return remainingCredits;
}
});
});
return Parse.Promise.when(promises);
}).then(function(results){
console.log(_.toArray(arguments));
status.success();
}, function(error){
status.error(error);
});
How can I calculate the remainingCredits with a specific order?
If it is important to process the asynchronously derived data in the original items order, then it should not be processed as it arrives.
Try waiting for all the data to arrive, then process it.
query.descending("createdAt");
return query.find().then(function(items) {
return Parse.Promise.when(_.map(items, function(item) {
return getUserPageView(123, new Date()).then(function(pageviews) {
//here, create an object with all the data required for later processing
return {
item: item,
pageviews: pageviews
};
});
}));
}).then(function() {
var remainingCredits = 0;
var runningBalance _.toArray(arguments).map(function(obj) {
var credit = obj.item.get("credit_buy");
var usedCredit = credit - obj.pageviews;
if(remainingCredits > 0)
return remainingCredits + credit;
if((credit - usedCredit) <= 0) {
console.log("usedCredit:" + usedCredit);
obj.item.set("used", true);
return 0;
} else {
remainingCredits += usedCredit;
return remainingCredits;
}
});
console.log(runningBalance);
status.success();
return runningBalance;
}, function(error) {
status.error(error);
});
I invented the variable name runningBalance because that is what you appear to be trying to create.
I tried to verify the processing of credits and can only suggest that it needs looking at again. For example, if usedCredit = credit - obj.pageviews, then the test if((credit - usedCredit) <= 0) {...} will simplify to if(obj.pageviews <= 0) {...}, which doesn't seem right.

Detect differences between two objects (JSON)

I've got a remote JSON file that contains the list of the last 100 users who logged into a service. This JSON is updated constantly and lists the users from the most recently logged in to the "least recently" logged in.
If the user who appears as number X logs back in, they get removed from their position X and put back at the very top of the JSON at position [0].
I retrieve the JSON every 5 minutes. What I'd like to do is detect the differences between the old object oldUsers and the new newUsers and store them in another object that would only contain the users who are present in newUsers but not in oldUsers. I have no real idea as to how to achieve this.
Here's the JSON structure:
[{
"id":"foo09",
"name":"John",
"age":28
}, {
"id":"bar171",
"name":"Bryan",
"age":36
},
...
]
Is there a rather straightforward way to do it? Thanks!
You need to write your own diff algorithm. Here is one I whipped up in JSBin:
I will need a utility function to merge two arrays (Underscore would help here).
function mergeArrays(val1, val2) {
var results = val1.splice(0);
val2.forEach(function(val) {
if (val1.indexOf(val) < 0) {
results.push(val);
}
});
return results;
}
Diff algorithm
function diff(val1, val2) {
var results = [];
var origKeys = Object.keys(val1);
var newKeys = Object.keys(val2);
mergeArrays(origKeys, newKeys)
.forEach(function(key) {
if (val1[key] === val2[key]) { return; }
var result = {
key: key,
orig: val1[key],
'new': val2[key]
};
if (val1[key] == null) {
result.type = 'add';
} else if (val2[key] == null) {
result.type = 'delete';
} else {
result.type = 'change';
}
results.push(result);
});
return results;
}

Categories

Resources