Pairing Similar objects of an array in AngularJS - javascript

I have a list of routers in array called routerList. I want to display the active router next to the backup router in my view. The router object in the array has an attribute called HostName that has the locationID_Router#_RouterName, for instance WA34_R01_ABCABC. Somewhere in the array is another router that is its pair with the name WA34_R02_ABCABC. I want to reorder the array so when I use ng-repeat those two routers and all the other matched pairs will be next to each other. I wrote a function that will tell me if the names are the same minus 1 character so R01 and R02. Here:
function stringCompare(word1, word2){
var differences = 0;
if(word1 != word2){
if(word1.length == word2.length){
for(i=0; i <= word1.length-1; i++){
if(word1.charAt(i) != word2.charAt(i)){
differences +=1;
}
}
}
}
if(differences == 1){
return true;
}else{
return false;
};
};
I then tried to have a loop within a loop to get the pairs and add them to a new array as it found the pairs but I keep getting errors of cannot read HostName part way through the loop.
function findCouples(array){
var MatchedRouters = [];
for(i=0;i<=array.length-1;i++){
for(var i2=0;i2<=array.length-1;i2++){
if(stringCompare(array[i].HostName,array[i2].HostName)){
MatchedRouters.push(array[i]);
MatchedRouters.push(array[i2]);
}
}
}
return MatchedRouters
};
If there is a better way to do this PLEASE let me know! If not any help you could give me for getting it to work like this would be amazing.
Thanks!!

When you initally get your list or routers create the properties you need to sort on.
Something like:
routers.forEach(function(router) {
router.location: getRouterLocation(router.HostName);
router.number: getRouterNumber(router.HostName);
router.name: getRouterName(router.HostName);
});
Then create your functions getRouterLocation, getRouterNumber, etc.. to parse out the values you need.
function getRouterLocation(hostName) {
return hostName.substring(0, hostName.indexOf('_');
}

Related

How do i push an array[i] to another array

Basically i have to create a quiz with 3category. each with 5questions.
I would have to push the selected category-questions into this new array from the array with all the questions. I am unable to do so.
pushSelectedQuestion() {
for (var i = 0; i < this.getNumberOfQuestion; i++) {
if (usercategory == questionPool[i].category) {
mcqSelected.push(questionPool[i])
return mcqSelected;
}
}
}
usercategory = input from user.
if user chooses category 1.
if (1 == questionPool[1].category) (if it matches the category) then it will be pushed.
This is the part which i cant do
Well, from the information you've provided, there's one main issue here - the return statement is definitely shortcutting the loop - so even if you have everything else right, you'll only ever get the first matching question. The rest will have been cut out by the return statement, which stops the function and returns the value.
pushSelectedQuestion() {
for (var i = 0; i < this.getNumberOfQuestion; i++) {
if (usercategory == questionPool[i].category) {
mcqSelected.push(questionPool[i])
// the below line is causing this loop to end after the first time through the list.
// Remove it and then put a console.log(mcqSelected);
// here instead to see the value during each iteration of the loop.
return mcqSelected;
}
}
}
There are a lot of ways to accomplish what you want to do here though. For example, you could just use the javascript Array.filter method like so
let selectedQuestions = questionPool.filter(question => question.category == userCategory)
Maybe I am not understanding your question correctly, but can't you use nested arrays. If the questions are categorized beforehand that is.

How to add/remove elements from array based on array contents

I've been struggling with this piece for a few days and I can't seem to find what's wrong. I have an array with a few objects:
myMainPostObj.categories = [Object, Object]
This is for add/removing categories to a post. Imagine I'm editing an existing post which is already associated with a couple of categories (as per code above).
I also have an array which has all categories in the db (including the ones which are associated with the post). On my js controller I have the following code:
$scope.addCategory = function (cat) {
for (var i in $scope.post.category_ids) {
if (cat._id === $scope.post.category_ids[i]) {
$scope.post.category_ids.slice(i, 1);
} else if (cat._id !== $scope.post.category_ids[i]) {
$scope.post.category_ids.push(cat._id);
}
}
}
The above function is called every time the user click on a category. The idea is for the above function to loop through the categories within the post (associated with the post) and compares it with the category passed as argument. If it matches the function should remove the category. If it doesn't it should add.
In theory this seems straight forward enough, but for whatever reason if I tick on category that is not associated with the post, it adds two (not one as expected) category to the array. The same happens when I try to remove as well.
This is part of a Angular controller and the whole code can be found here
The error in your code is that for each iteration of the loop you either remove or add a category. This isn't right... You should remove if the current id matches but add only if there was no match at all. Something like this:
$scope.addCategory = function (cat) {
var found = false;
for (var i in $scope.post.category_ids) {
if (cat._id === $scope.post.category_ids[i]) {
$scope.post.category_ids.splice(i, 1); // splice, not slice
found = true;
}
}
if (!found) // add only if it wasn't found
$scope.post.category_ids.push(cat._id);
}
I guess the problem could be that you're altering the category_ids array while you're iterating over it with the for loop. You might be better off trying something like this:
$scope.addCategory = function (cat) {
var catIndex = $scope.post.category_ids.indexOf(cat._id);
if (catIndex > -1)
$scope.post.category_ids.splice(catIndex, 1);
else
$scope.post.category_ids.push(cat._id);
}
Note that indexOf doesn't seem to be supported in IE7-8.
Let's simplify this a bit:
const CATEGORIES = [1, 2, 3];
let addCategory = (postCategories, categoryId) => {
CATEGORIES.forEach((cId, index) => {
if (postCategories[index] === cId) console.log("Removing", categoryId);
else console.log("Adding", categoryId);
});
return postCategories;
};
Please ignore the fact that we actually are not mutating the array being passed in.
A is either equal or not equal to B - there is no third option (FILE_NOT_FOUND aside). So you are looping over all of your categories and every time you don't find the category ID in the array at the current index you add it to the postCategories array.
The proper solution to your problem is just to use a Set (or if you need more than bleeding edge ES6 support, an object with no prototype):
// Nicer, ES6-or-pollyfill option
var postCategories = new Set();
postCategories.add(categoryId);
// Or, in the no-prototype option:
var postCategories = Object.create(null);
postCategories[categoryId] = true;
// Then serialization needs an extra step if you need an array:
parentObject.postCategories = Object.keys(parentObject.postCategories);

Can I loop through 2 objects at the same time in JavaScript?

related (sort of) to this question. I have written a script that will loop through an object to search for a certain string in the referring URL. The object is as follows:
var searchProviders = {
"google": "google.com",
"bing": "bing.com",
"msn": "search.msn",
"yahoo": "yahoo.co",
"mywebsearch": "mywebsearch.com",
"aol": "search.aol.co",
"baidu": "baidu.co",
"yandex": "yandex.com"
};
The for..in loop I have used to loop through this is:
for (var mc_u20 in mc_searchProviders && mc_socialNetworks) {
if(!mc_searchProviders.hasOwnProperty(mc_u20)) {continue;}
var mc_URL = mc_searchProviders[mc_u20];
if (mc_refURL.search(mc_URL) != -1) {
mc_trackerReport(mc_u20);
return false;
}
Now I have another object let's call it socialNetworks which has the following construct:
var socialNetworks = {"facebook" : "facebook.co" }
My question is, can I loop through both of these objects using just one function? the reason I ask is the variable mc_u20 you can see is passed back to the mc_trackerReport function and what I need is for the mc_u20 to either pass back a value from the searchProviders object or from the socialNetworks object. Is there a way that I can do this?
EDIT: Apologies as this wasn't explained properly. What I am trying to do is, search the referring URL for a string contained within either of the 2 objects. So for example I'm doing something like:
var mc_refURL = document.referrer +'';
And then searching mc_refURL for one of the keys in the object, e.g. "google.com", "bing.com" etc. 9this currently works (for just one object). The resulting key is then passed to another function. What I need to do is search through the second object too and return that value. Am I just overcomplicating things?
If I understand your question correctly, you have a variable mc_refURL which contains some URL. You want to search through both searchProviders and socialNetworks to see if that URL exists as a value in either object, and if it does you want to call the mc_trackerReport() function with the property name that goes with that URL.
E.g., for mc_refURL === "yahoo.co" you want to call mc_trackerReport("yahoo"), and for mc_ref_URL === "facebook.co" you want to call mc_trackerReport("facebook").
You don't say what to do if the same URL appears in both objects, so I'll assume you want to use whichever is found first.
I wouldn't create a single merged object with all the properties, because that would lose information if the same property name appeared in both original objects with a different URL in each object such as in an example like a searchProvider item "google" : "google.co" and a socialNetworks item "google" : "plus.google.com".
Instead I'd suggest making an array that contains both objects. Loop through that array and at each iteration run your original loop. Something like this:
var urlLists = [
mc_searchProviders,
mc_socialNetworks
],
i,
mc_u20;
for (i = 0; i < urlLists.length; i++) {
for (mc_u20 in urlLists[i]) {
if(!urlLists[i].hasOwnProperty(mc_u20))
continue;
if (mc_refURL.search(urlLists[i][mc_u20]) != -1) {
mc_trackerReport(mc_u20);
return false;
}
}
}
The array of objects approach is efficient, with no copying properties around or anything, and also if you later add another list of URLs, say programmingForums or something you simply add that to the end of the array.
You could combine the two objects into one before your loop. There's several approaches here:
How can I merge properties of two JavaScript objects dynamically?
var everything = searchProviders;
for (var attrname in socialNetworks) { everything[attrname] = socialNetworks[attrname]; }
for(var mc_u20 in everything) {
// ...
}
for (var i = 0; i < mc_searchProviders.length; i++) {
var searchProvider = mc_searchProviders[i];
var socialNetwork = mc_socialNetworks[i];
if (socialNetwork != undefined) {
// Code.
}
}
Or am i horribly misunderstanding something?

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