Efficient mapping of multiple inputs to a single output [duplicate] - javascript

Using JavaScript I am pulling names out of webpage and stringing them together somehow (probably going with an array). Once I gather all the names together I need to make another string that gives all the email addresses of the names. The email addresses are not on the webpage so I will have to list every possible thisName=thisEmail in my script somehow. I was about to approach this with making a bazillion if statements but I thought there has to be a more efficient way. Any suggestions?
var x = getElementById("names");
var name = x.InnerHTML;
var email;
if (name == 'Steve'){ email == 'steve462#gmail.com'; }
if (name == 'Bob'){ email == 'duckhunter89#gmail.com'; }
....

A switch statement, as your code is only if-elses :-)
No, honestly. The best thing would be if you'd find a simple algorithm to create an email address from any given name, like
function mail(name) {
return name.toLowerCase() + "#gmail.com";
}
var email = mail("Bob") // example usage
If they differ to much, you might use an object as a key-value-map:
var mails = {
"Steve": "steve#gmail.com",
"Bob": "bob1#freemail.org",
...
}
var email = mails[name];
You could also combine those, if you have to determine which algorithm you need to use:
var map = [{
algorithm: function(name) { return name+"#something"; },
names: ["Steve", "Bob", ...]
},{
algorithm: function(name) { return "info#"+name+".org"; },
names: ["Mark", ...]
}];
for (var i=0; i<map.length; i++)
if (map[i].names.indexOf(name) > -1) {
var email = map[i].algorithm(name);
break;
}
or when it is a bit simpler:
var domains = {
"gmail.com": ["Steve", "Bob", ...],
"free.xxx": ["Mark", ...],
...
};
for (var domain in domains)
if (domains[domain].indexOf(name) > -1)
var email = name.toLowerCase()+"#"+domain;
break;
}
Just try to reduce the amount of data to deliver to the client as much as you can.

You can store all the email address in an associative array like
pseudo code
var emailsList = ["steve" => "steve#gmail.com", "bob" => "bob#gmail.com"];
then email = emailsList[name]; will solve your problem

You could create an object in advance:
var name_email_map = {
"Steve": "steve#gmail.com",
"Bob": "bob#gmail.com",
"John": "j7hogli123123#telus.net"
}
This would be easy to output from some server side language with a JSON library for whatever language you're using. There is a list of JSON libraries at the bottom of this page: http://www.json.org/
If you're using PHP on the server side you can just json_encode an associative array, which you may have selected from a database.
var name = 'Bob'; //x.innerHTML;
var email = name_email_map[name];
alert(email); // Alerts bob#gmail.com
alert(name_email_map['John']); // Alerts j7hogli123123#telus.net

Related

Trying to generate an array of hashes in Node from model object

In order to send an email to multiple recipients via SendGrid API v3 using a dynamic template, I need to pass an email parameter like:
"to":[
{
"email":"example1#example.com"
},
{ "email": "example2#example.com"
}
],
Obviously I am not wanting to hard code these email addresses s.t. they are dynamic.
I currently generate a list of emails with this code:
// loop through users
var users = group.user;
var emails = users.map(function (obj) {
return obj.email;
});
Which returns eg:
[ 'example1#example.com',
'example2#example.com' ]
How do I return instead the array of hashes:
[
{
"email":"example1#example.com"
},
{ "email": "example2#example.com"
}
]
Maybe what you are trying to say is hashmap, not hashes, if not, I don't understand the question.
To achieve the lists of maps that you mention, your code should be something like:
// loop through users
var users = group.user;
var emails = users.map(function (obj) {
return {email: obj.email};
});
Every item of the list would have email as key, and the email as value.
What is a hash: https://en.wikipedia.org/wiki/Hash_function
What is a hash table: https://en.wikipedia.org/wiki/Hash_table
What is a js object: https://www.w3schools.com/js/js_objects.asp

Object of Names / split into separate objects or arrays

I am looking for some general advice about how I should be thinking to go about doing this.
What I need to do is take an object that has "usernames" : userId, etc.. and split them into separate objects or arrays with each object only containing usernames that start from a certain letter.
So right now I have:
allusers = {"adam292":10302, "alex92":12902, "briannv999":10302, "sandra127":11102, "sam11":100 }
but I need to split them into their own objects or arrays like the following:
ausers = { "adam292":10302, "alex92":12902 }
busers = { "briannv999":10302 }
susers = {"sandra127":11102, "sam11":1002 }
I am doing this because I need to display a dialog box that also shows the letters a - z which would be links that you can click to display users that start with that letter.
Any advice is very much appreciated!
Here is one way to do it:
Working Fiddle
looping through the object we grab the first letter and check to see if we have a key for it in our users object, if not we make one and assign an array (containing the user data) to it, if yes we push to that array:
var users = {};
for (var user in allusers) {
var firstLetter = user.slice(0,1);
if (users[firstLetter]) {
users[firstLetter].push([user, allusers[user]]);
}
else {
users[firstLetter] = [[user, allusers[user]]];
}
}
The output of the code above using your example object is the following:
{
a: [["adam292", 10302], ["alex92", 12902]],
b: [["briannv999", 10302]],
s: [["sandra127", 11102], ["sam11", 100]]
}
you can do this in a loop:
letter2users = {}
for (var uname in allusers) {
if (!letter2users[uname[0]]) {
letter2users[uname[0]] = [];
}
letter2users[uname[0]].push(allusers[uname]);
}
# access this by using letter2users.a lettersusers.b

Two javascript arrays, using a key to look up

I have two data structures (they are much longer, these are just excerpts)
var data = [
{count: 6, zip: "78705"},
{count: 4, zip: "78754"},
{count: 33, zip: "78757"}
]
var txcodes = [
{county: "SWISHER", code: "437"},
{county: "TARRANT", code: "439"},
{county: "TAYLOR", code: "441"},
{county: "TRAVIS", code: "453"}
]
I have written code that successfully goes through “data” and takes the zipcode and retrieves the corresponding county (from an external website via HTTP request). It returns a structure that looks like
results = {
TRAVIS: 8,
TAYLOR: 1
}
(8 and 1 are examples of counters for how many times a zipcode from data occurs…basically a running count).
What I need to do next is use the keys from results to look up what the corresponding code in txcodes is. How do I do this?
var currentCounty = str.result[0].County
returns the county from results.
console.log(txcodes[i].county + " " + txcodes[i].code)
prints the county & code from txcodes.
I’m a little confused on how to do this. It seems like a relatively simple concept but I can’t seem to get the desired result. Can someone please point me in the right direction?
If county names are unique and if you are going to be making repeated lookups, you should build a "map" of the codes out of the array:
var txcodesByCounty = txcodes.reduce(function(p, c) {
p[c.county] = c.code;
return p;
}, {});
You can then look up codes directly from this map.
Build a lookup map like this :
var lookupMap = {};
for (var i = 0; i < txcodes.length; i++) {
var element = txcodes[i];
lookupMap[element.county] = element;
}
Then you can simply do this to print the desired output :
console.log(lookupMap[currentCounty].county + " " + lookupMap[currentCounty].code);
If the county in your result is only available as a key, you'll need to for..in, Object.keys or Object.getOwnPropertyNames to access them.
After, access the details via a map as others have suggested
var county, found = [];
for (county in results)
found.push(map[county]);
So what you get back from your HTTP request is a simple object, and you need to access its property names. You can do that easily with Object.keys:
resultKeys = Object.keys(result);
This will give you an array of the object properties:
[ "TRAVIS", "TAYLOR" ]
You can easily iterate over this array now, and inside you ask your result object for its value:
for (var i = 0; i < resultKeys.length; i++) {
console.log(resultkeys[i] + ": " + result[resultkeys[i]]);
}
Using this technique, you can use for example underscore.js libary to easily filter for your desired data:
for (var i = 0; i < resultKeys.length; i++) {
console.log(_.filter(txcodes , function(key){ return txcodes.county== resultkeys[i]; }));
}

underscore find method issue on array of objects

I have following array of objects
var ppl = [
{
name: "John",
content: "<p>description</p>"
},
{
name: "Mike",
content: "<p>Desc</p>"
},
{
name: "Steve",
content: "html"
},
{
name: "Michael",
content: "<p>description</p>"
}
];
What I am doing is to display above array. Then when user clicks on name return his content. Like following
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
var content = _.find(ppl, function (desc) { if (desc.name === text) return desc.content; });
console.log(content);
});
What above code does is it finds the content of the person clicked however it returns the entire object of that person e.g. when John is clicked the his entire object {
name: "John",
content: "<p>description</p>"
} is returned by the _.find() function. I just need the content. How can I return content only?
If I were you I would simply do a loop:
var length = ppl.length;
var findcat = function(){
for (var a = 0; a < length; a++) { if(ppl[a].name==text){return ppl[a].content} };
}
var content = findcat();
rather than using underscore.js .
Or if you really want to use underscore.js, change it to this:
var content = _.find(ppl, function (desc) { if (desc.name === text) return desc; });
content = content.content;
and it will work.
Updates (regarding HTML strings in json):
It is okay to store them in json as these HTML strings will simply be considered as normal strings data (just don't forget to escape characters like quotation and forward slash). When real HTML elements are being created from these strings (using jquery functions like .html(string), append(string) ), the browser will need to render these new contents and it may cause a slow performance comparing to leaving all the page-rendering at the start for the browser, but the difference will be pretty subtle. So in terms of performance, it is always okay to have them in json. But in terms of security, you should be careful when there were HTML markup in your data because you are making XSS easier to be accomplished. (Here is a wikipedia article that provides more details on XSS, also known as Cross-site scripting.)
I don't think you need an array here. A simpler and more efficient way would be to use names as properties.
var ppl = {"John": "<p>description</p>", "Mike": "<p>Desc</p>" };
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
console.log(ppl[text]);
});
This is the expected Behavior of find operator which returns whole found item ! , why dont use content.content
the _.find looks through each value in the list, returning the first one that passes a truth test, when you return desc.content, it is evalued to true, so the desc object is return. so you can't return inside the find. but you can just access the content as desc.content. here is jsfiddle code:
$('a.ppl').on('click', function (e) {
e.preventDefault();
var text = $(this).text();
var desc = _.find(ppl, function (desc) {
return desc.name === text;
});
console.log(desc.content);
});

Can't make a function that finds the value using the key with a JSON array using jQuery

I attempting to pull data from a JSON file. I cannot change the way the data is keyed or labeled in the file since it is being converted from a CSV file.
My JSON data looks like this (I am using a grep filter and then storing it in a variable but for brevity I am not showing that part unless someone needs to see it):
var medicare = {
"": "",
"80101": "NC",
"80104": "NC",
"80152": "24.61",
"80154": "22.72",
"80299": "18.83",
"82055": "14.85",
"82145": "9.71",
"82542": "16.01",
"82646": "23.91",
"82649": "23.91",
"83805": "24.23",
"83840": "13.04",
"83887": "22.26",
"83925": "26.74",
"83992": "20.20",
"99080": "NC",
"99358": "NC",
"Carrier Type": "Medicare",
"G0434": "12.17",
"State": "Minnesota",
"id": 122
}
I have managed to load the file using $.getJSON() and I have also managed to make a filter using $.grep() to filter arrays by State and Carrier Type. Now I need to create a function that will be able to return the value of any of the given keys.
function findInside( array, key ) {
return array[key]; // <-- This is my problem.
}
Which I can use to return value by running:
console.log(findInside(medicare, "80101"))
I just need to be able to get the value. I don't think I need to do any loops and such. I'm still new to JavaScript and am banging my head over this one, and it should be pretty easy.
Thanks in advance!
EDIT: Here is all the relevant code code except the JSON file. I wish I wasn't using window.numbers the way I am but I being so new to this, I didn't know any other way to make it work.
jQuery(document).ready(function($) {
// First things first, fill the state picker.
$.each(usStates, function(i, option) {
$('#state').append($('<option/>').attr("value", option.abbreviation).text(option.name));
});
// Next we need to load in the JSON Data file.
$.getJSON('data.json', function(data) {
window.numbers = data
});
$("#state").change(function(){
//Lets get the stuff in the fields.
state = $("#state").val();
stateName = $("#state option:selected").text();
//Filter all through all the data.
var workersComp = filterData("Worker's Comp", stateName);
var commercial = filterData("Commercial", stateName);
var medicare = filterData("Medicare", stateName);
var medicaid = filterData("Medicaid", stateName);
console.log(medicare);
console.log(findInside(medicare, "80101")); // undefined
});
})
//Functions
function filterData( i, d) {
var r = $.grep( window.numbers, function(val, index) {
return val.State === d;
});
var output = $.grep(r, function(val, index) {
return val["Carrier Type"] === i;
});
return output
}
function findInside( array, key ) {
return array[key];
}
jQuery's .grep() method returns an array of answers.
Your logic here that filters the data is receiving an array of results back. If you are guaranteed to have one and only one of each item, the short fix is to change:
//Filter all through all the data.
var workersComp = filterData("Worker's Comp", stateName);
var commercial = filterData("Commercial", stateName);
var medicare = filterData("Medicare", stateName);
var medicaid = filterData("Medicaid", stateName);
To this (gets the first element in the resulting array for each type):
//Filter all through all the data.
var workersComp = filterData("Worker's Comp", stateName)[0];
var commercial = filterData("Commercial", stateName)[0];
var medicare = filterData("Medicare", stateName)[0];
var medicaid = filterData("Medicaid", stateName)[0];
The longer term fix is to revisit your filtering logic a bit and see if you can come up with a better pattern.
For Example: If you could work your data into a form that looks something like:
var states = {
…,
"Minnesota": {
"Worker's Comp": {…},
"Commercial": {…},
"Medicare": {
"80101": "NC",
"80104": "NC",
"80152": "24.61",
...
},
"Medicaid": {…}
},
...
}
Selecting the right value could be simplified to:
states[stateName]["Medicare"]["80101"]

Categories