Compare two lists and remove common elements using angular js - javascript

I am having 2 lists like below
list1 =
['option1','option2','option3','option4','option5','option6','option7'];
list2 = ['option3', 'option4', 'option7'];
I want the list to be
listFinal = ['option1','option2','option5','option6','option7'];
Please give me the suggestion using angular js how to solve this using filter
Tried to use this code to solve this using filter but unable to succeed.
app.filter('unique', function() {
return function(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
});

I'm not sure that you really want a filter here. This is something that you should probably solve outside of Angular. If you're willing to add lodash to your project, you could do this:
var diff = _.difference(array1, array2);
If you must use a filter, you could try something like this?
app.filter('difference', function() {
return function(input, diff_array) {
var result = [];
for (var i = 0; i < input.length; i++) {
if (diff_array.indexOf(input[i]) == -1) {
result.push(input[i]);
}
}
return result;
}
}
Note that if you do this, your template has to look something like:
{{ input | difference:diff_arr }}
I haven't actually tested any of this, but this should be the general idea. I concur with Phillip that this really isn't something you should try to solve in Angular.

What you are describing is an "array/set difference". There are many questions on StackOverflow asking about this already. This is not related to Angular.js, but is an problem with an algorithmic solution. Just to add bit of interesting material, a "naive" solution runs in O(nlogn) which would be:
Sort the two lists/arrays from lowests to highest
Traverse each array setting the internal pointer to 0 initially, compare the elements. If the element in Array A is larger than the on in Array B advance the pointer by 1 in Array B, else B, else if they are equal, remove the result from the array and advance both pointers
What is the fastest or most elegant way to compute a set difference using Javascript arrays?
JavaScript array difference

Related

Differences between js objects

I got the following problem and I am looking for a really efficient way to do this.
I got two Javascript Objects always build like {id:data,id:data,..}
If I only look on the Keys they will look like this:
B = ["1","2","3"]
A = ["2","3","4"]
Now I need the information what i need to do, to transform B into A, so in this case: Delete B.1 and B.4 = A.4 .
I was thinking that maybe a prototyp function for Object would be a good way to do this.
This is what i have so far:
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
Object.prototype.syncTo = function(b,callbackA,callbackB){
var a = this;
var bKeys = Object.keys(b);
var aKeys = Object.keys(a);
var toremove = bKeys.diff(aKeys);
var toadd = aKeys.diff(bKeys);
for(var i = 0; i < toremove.length; i++) {
if(b.hasOwnProperty(toremove[i])) {
delete b[toremove[i]];
}
}
callbackB(b);
for(var i = 0; i < toadd.length; i++) {
if(a.hasOwnProperty(toadd[i])){
<<Dont know how to go on now>>
}
}
callbackA(XXXXXX);
};
Where CallbackA should be called with all elements that have to be added to B and CallbackB should be called with all elements that need to be removed from B.
I am struggling With the elements for callbackA and in general whether this is an efficient way of doing this.
Thank you for your support !
EDIT:
An Example for one of the Callbacks would be :
callbackB:
function (items){
for(var i in items){
items[i].removeSomeWhereElse();
}
}
There are a couple of libraries that can do this if your search NPM, as a shameless plug I'll just mention one I authored that diffs any object, including array insertion/deletion/moves:
https://github.com/benjamine/jsondiffpatch
here's the DEMO page diffing 2 arrays, as you need:
http://benjamine.github.io/jsondiffpatch/demo/index.html?desc=moving%20around&left=%5B0%2C1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%5D&right=%5B10%2C0%2C1%2C7%2C2%2C4%2C5%2C6%2C88%2C9%2C3%5D
you can see deletes, adds, and even moves (move detection can be disabled by configuration if you want)
Using library will be the more efficient in saving your time, now if you want to save CPU cycles instead, you could just use a simple implementation of LCS (which is the standard algorithm to solve to the problem you're describing), see: https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
jsondiffpatch includes that (for js), and you can steal it from here: https://github.com/benjamine/jsondiffpatch/blob/master/src/filters/lcs.js

Removing a value in an object based on if it contains a string

a fairly simple question today.
I have an object that looks like this:
var buttonLogos = {
adcraft: [".","..","1.png","2.png","3.png"],
ferries: [".","..","1.png","2.png"]
}
and I'm looking for a quick way to remove the entries at the beginning with the dots, I would usually just filter out anything with a dot, but I can't because the strings I want contain a .png
it might be a solution to filter out the first two entries, because they will always be "." and ".." but alas I'm not sure how to even do that.
(jQuery is encouraged)
I would love some help! Thanks.
for(i in buttonLogos){
buttonLogos[i] = buttonLogos[i].filter(function(i){
return !i.match(/^\.{1,2}$/);
});
}
You can use js regex as follows,
buttonLogos.adcraft = $(buttonLogos.adcraft).filter(function(i,val){return val.match(/[^\.]/);});
Filters as mentioned in other answers or a combination of indexOf and splice would also work.
var adcraft = [".","..","1.png","2.png","3.png"];
var elems_to_rm = [];
for (var i = 0; i < adcraft.length; i++) {
if (adcraft[i].indexOf('.') === 0) {
elems_to_rm.push(adcraft[i]);
}
}
for (var i = 0; i < elems_to_rm.length; i++) {
var index = adcraft.indexOf(elems_to_rm[i]);
adcraft.splice(index, 1);
}
Try manually. Any number of items can be deleted from the array by specifying just two
arguments: the position of the first item to delete and the number of items to delete. For
example, splice(0, 2) deletes the first two items.

I want object keys to check for duplicates, but I also want to sort the objects later, what should I do?

I have an array called newposts
I itterate through it and if it meets certain criteria, I add it to another array:
for (newpost in newposts){
if (!( newposts[newpost][0] in currentposts )){
var triploc1 = locations[newposts[newpost][1]].location;
var triploc2 = locations[newposts[newpost][2]].location;
var detour_distance = fourpoint_distance(newloc1, triploc1, triploc2, newloc2);
if (worthwhile_detour(original_distance,detour_distance)){
currentposts.push(posts[newposts[newpost][0]])
}
}
}
The second row, is intended to check for duplicates(newposts[newpost][0]) is an ID. When I wrote it I had forgotten that currentposts was an array. Obviously, this doesn't work. I need currentposts to be an array, because just below i sort it. I could ofcourse convert it into an array once the selection is done. But I'm new to javascript and believe someone might know a better way to do this.
function sortposts(my_posts){
my_posts.sort(function(a, b) {
var acount = a.sortvar;
var bcount = b.sortvar;
return (bcount-acount);
});
}
I'm not exactly sure what your desired goal here is, but I can try and clean this up for you. Please note that I'm using the underscore.js library as it makes working with arrays a HECK OF A LOT easier :) If you can't include underscore.js into your project, let me know and I'll write it in "pure" javascript :)
_.each(newposts, function(item) {
if ( _.indexOf(currentposts, posts[item[0]]) >= 0 ) {
var triploc1 = locations[item[1]].location;
var triploc2 = locations[item[2]].location;
var detour_distance = fourpoint_distance(newloc1, triploc1, triploc2, newloc2);
if (worthwhile_detour(original_distance, detour_distance)){
currentposts.push(posts[item[0]])
}
}
});
_.sortBy(currentposts, function(item) {
return item.sortvar;
});
I have to question, however, why you're using so many arrays (newposts, locations, posts, etc)? Are they all needed?

javascript - coldfusion - working with a list

This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.
Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}
Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function
Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/
I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;

Need help with setting multiple array values to null in a loop - javascript

I have been working on creating a custom script to help manage a secret questions form for a login page. I am trying to make all the seperate select lists dynamic, in that if a user selects a question in one, it will no longer be an option in the rest, and so on. Anyways, the problem I am having is when I try to set the variables in the other lists to null. I am currently working with only 3 lists, so I look at one list, and find/delete matches in the other 2 lists. Here is my loop for deleting any matches.
for(i=0; i<array1.length; i++) {
if(array2[i].value == txtbox1.value) {
document.questions.questions2.options[i] = null
}
if(array3[i].value == txtbox1.value) {
document.questions.questions3.options[i] = null
}
}
This works fine if both the matches are located at the same value/position in the array. But if one match is at array1[1] and the other match is at array3[7] for example, then only the first match gets deleted and not the second. Is there something I am missing? Any help is appreciated. Thanks!
I don't see too many choices here, considering that the position in each array can vary.
Do it in separate loops, unless of course you repeat values in both arrays and share the same position
EDTI I figured out a simple solution, it may work, create a function. How about a function wich recives an array as parameter.
Something like this:
function finder(var array[], var valueToFound, var question) {
for (i=0; i<array.lenght; i++) {
if (array[i].value == valueToFound) {
switch (question) {
case 1: document.questions.questions1.options[i] = null;
break;
}
return;
}
}
}
I think i make my point, perhaps it can take you in the right direction
My bet is that the code isn't getting to array3[7] because either it doesn't exist or that array2 is too short and you're getting a JavaScript exception that's stopping the code from doing the check. Is it possible that array2 and array3 are shorter than array1?
It is more code, but I would do it like this:
var selectedvalue == txtbox1.value;
for(i=0; i<array2.length; i++) { // iterate over the length of array2, not array1
if(array2[i].value == selectedvalue) {
document.questions.questions2.options[i] = null;
break; // found it, move on
}
}
for(i=0; i<array3.length; i++) {
if(array3[i].value == selectedvalue) {
document.questions.questions3.options[i] = null;
break; // you're done
}
}

Categories