Validating list of email extention set as JSON in JavaScript - javascript

How can I validate user inputted email and check their extension with a list of email extensions in a JSON?
Like if I type abc#efg.com its going to check only the email extension which is #efg.com in a list of JSON.
OR a regex that will only get the values after "#" and ignore anything before that.
[
{
"School": "Ivy Tech Community College",
"Email": "ivytech.edu"
},
{
"School": "Liberty University",
"Email": "liberty.edu"
},
{
"School": "Miami Dade College",
"Email": "mdc.edu"
},
{
"School": "Lone Star College",
"Email": "lonestar.edu"
},
{
"School": "Ashford University",
"Email": "ashford.edu"
}
]

// initial data
var data = '[ {"School":"Ivy Tech Community College","Email":"ivytech.edu"},' + '{"School":"Liberty University","Email":"liberty.edu"},' + '{"School":"Miami Dade College","Email":"mdc.edu"},' + '{"School":"Lone Star College","Email":"lonestar.edu"},' + '{"School":"Ashford University","Email":"ashford.edu"} ]';
// json-ify our data
var jsonData = JSON.parse(data);
// map the values of each JSON 'Email' property from jsonData in an array
var emailsArray = jsonData.map(function (x) { return x.Email; });
// email address for testing
var testEmail = "john#liberty.edu";
// split the email address by the "#" character and use the second part (domain)
if (arrayContains(testEmail.split("#")[1], emailsArray))
{
// this will fire as john#liberty.edu matches liberty.edu in emailsArray
console.log("emailsArray contains domain");
}
else
{
console.log("emailsArray does not contain domain");
}
// function to check if an item is contained in an array
function arrayContains(item, array)
{
return (array.indexOf(item) > -1);
}
Complete JSFiddle example here.
Notes:
you can ignore the first two lines of code as I'm guessing you're getting your JSON data from a web response
an assumption is being made that testEmail adheres to the format of an email address; you might need to implement some kind of validation to verify that the string being input is an actual email
we split testEmail by the # character and get the second part of the result (which will be at index 1, since arrays are zero-based) using String.prototype.split()
the emailsArray array is created using the Array.prototype.map() function
arrayContains uses the String.prototype.indexOf() method to check if testEmail exists in emailsArray
I think I've clarified what every line of code in the example does. You can now take it and adjust it to your own requirements—and even better, improve it.

Instead of regex, you can iterate through the array of schools, and match the domain like this:
var schools = [
{"School":"Ivy Tech Community College","Email":"ivytech.edu"},
{"School":"Liberty University","Email":"liberty.edu"},
{"School":"Miami Dade College","Email":"mdc.edu"},
{"School":"Lone Star College","Email":"lonestar.edu"},
{"School":"Ashford University","Email":"ashford.edu"}
]
function validate(email) {
var domain = email.split('#').pop();
for(var i = 0; i < schools.length; i++) {
if(domain === schools[i].Email) return schools[i].School;
}
return 'Domain Not Found';
}
You can replace schools[i].School with true and 'Domain Not Found' with false to just check with it exists.
Example: https://jsfiddle.net/TheQueue841/gwhkq520/

Something like trashrOx mentioned would work:
var edus = [
{"School":"Ivy Tech Community College","Email":"ivytech.edu"},
{"School":"Liberty University","Email":"liberty.edu"},
{"School":"Miami Dade College","Email":"mdc.edu"},
{"School":"Lone Star College","Email":"lonestar.edu"},
{"School":"Ashford University","Email":"ashford.edu"}
];
var emails = ['matty.fake#lonestar.edu','himom#mdc.edu','randomguy#yahoo.com'];
emails.forEach(function(element,index) {
var domain = element.substring(element.indexOf('#') + 1);
var match = 'none';
if (domain) {
edus.forEach(function(element,ind) {
if (element.Email === domain) {
match = element.School;
}
});
console.log(element + ' matched ' + match);
}
});
// matty.fake#lonestar.edu matched Lone Star College
// himom#mdc.edu matched Miami Dade College
// randomguy#yahoo.com matched none

Use Array.prototype.some() if you only want to validate.
some() executes the callback function once for each element present in the array until it finds one where callback returns a truthy value (a value that becomes true when converted to a Boolean). If such an element is found, some() immediately returns true. Otherwise, some() returns false. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
var schools = [
{"School":"Ivy Tech Community College","Email":"ivytech.edu"},
{"School":"Liberty University","Email":"liberty.edu"},
{"School":"Miami Dade College","Email":"mdc.edu"},
{"School":"Lone Star College","Email":"lonestar.edu"},
{"School":"Ashford University","Email":"ashford.edu"}
]
function validate(email) {
var domain = email.split('#').pop();
return schools.some(function(school) {
return school.Email === domain;
});
}
validate('test#ashford.edu');

Related

Pouchdb join / link documents

I have pouchdb/couchbase data with equipment that has user assigned to them.
Equipment with _id and in the equipment doc there is a checkedOutBy with the user._id as the value. Within the employee object there is user.name. When I get the equipment objects how do I also get the user.name and display with the equipment.
I have searched and read about map/reduce that uses emit and do not grasp the idea. My code that i wrote from what i learned is:
by the way I am also using Angularjs.
field = "eq::"
this.getAllEquip = function(field){
function map(doc) {
if (doc.checkedOutBy !== undefined) {
emit(doc.checkedOutBy, {empName : doc.name});
}
}
var result = database.query(map, {include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'})
.catch(function (err) {
//error stuff here
});
return result
};
I don't see where the two docs would get together. What am i missing? My result is empty.
The equipment json looks like:
{checkedOutBy: "us::10015", description: "3P Microsoft Surface w/stylus & power cord", equipId: "SUR1501", purchaseDate: "", rCost: 1000, id:"eq::10001"}
Emlpoyee json:
{"firstname":"Joe","gender":"male","lastname":"Blow","status":"active","title":"office","type":"userInfo","_id":"us::10015","_rev":"2-95e9f34784094104ad24bbf2894ae786"}
Thank you for your help.
Something like this should work, if I understood the question correctly:
//Sample Array of Objects with Equipment
var arr1=[{checkedout:"abc1",desc:"item1",id:1},
{checkedout:"abc2",desc:"item2",id:2},
{checkedout:"abc3",desc:"item3",id:3},
{checkedout:"abc1",desc:"item1",id:4},
{checkedout:"abc4",desc:"item3",id:5},
{checkedout:"abc6",desc:"item3",id:6}];
//Sample array of objects with Employee - the "id" in arr2 matches with "checkout" in arr1
var arr2=[{name:"john",id:"abc1"},
{name:"jack",id:"abc2"},
{name:"alice",id:"abc3"},
{name:"james",id:"abc4"}];
var result = []; //final result array
//loop through equipment array arr1
arr1.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.checkedout;
//do array.find which will return the first element in the array which satisfies the given function. This is absed on the assumption that that the id is unique for employee and there wont bwe multiple employees with same id (which is the "checkedout" field in equipment. If the employee is not found, it will return undefined.
var foundname = arr2.find(function(obj) {
if (obj.id == checkedout_id)
return obj.name
})
//Create the object to be inserted into the final array by adding a new key called "name", based on the result of above find function
if (foundname != undefined) {
tempObj.name=foundname.name
}
else {
tempObj.name = "Not found";
}
result.push(tempObj);
})
This is my Pouchdb solution, thank you Vijay for leading me to this solution.
First I get all my equipment. Then I use Vijay's idea to loop through the array and add the name to the object and build new array. I found there is a need to go into the .doc. part of the object as in obj.doc.checkedOutBy and tempObj.doc.name to get the job done.
$pouchDB.getAllDocs('eq::').then(function(udata){
var result = [];
//loop through equipment array
udata.rows.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.doc.checkedOutBy;
if (checkedout_id != undefined) {
$pouchDB.get(checkedout_id).then(function(emp){
return emp.firstname + " " + emp.lastname
}).then(function(name){
tempObj.doc.name = name;
});
}
result.push(tempObj);
})
in my service I have:
this.get = function(documentId) {
return database.get(documentId);
};
and:
this.getAllDocs = function(field){
return database.allDocs({
include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'});
};

Efficient way to search within multiple values in json

I have multiple records like this,
name: John Doe aliases: John, Doe, JD unique_id: 1 ...
My question is how do I search efficiently within the aliases & full name.
If the search query is any of those 4 (John Doe, John, Doe, JD) I would like to find the unique id (in this case 1).
What I have done: I have a very straightforward implementation that loops through the entire data until it finds. It takes a long time since the number of fields is very high.
Note: I am using javascript if it helps. Also I have the permission to change the data format (permanently), if it will make the search more efficient. Most of the search queries tend to be one of the aliases rather than full name.
Sample Code: https://jsfiddle.net/nh7yqafh/
function SearchJSON(json, query) {
var champs = json.champs;
for (var i = 0; i < champs.length; ++i) {
if (query == champs[i].name)
return champs[i].unique_id;
for (var j = 0; j < champs[i].aliases.length; ++j) {
if (query == champs[i].aliases[j])
return champs[i].unique_id;
}
}
}
//Data format is similar to what vivick said
var json_string = '{"count":5,"champs":[{"name":"Abomination","aliases":["abomination","AB","ABO"],"unique_id":1},{"name":"Black Bolt","aliases":["blackbolt","BB","BBT"],"unique_id":2},{"name":"Black Panther","aliases":["blackpanther","BP","BPR"],"unique_id":3},{"name":"Captain America","aliases":["captainamerica","CA","CAP"],"unique_id":4}]}'
var json = JSON.parse(json_string);
query="CA";
alert( "id of "+query+" is "+SearchJSON(json, query));
I guess you have a structure similar to the following one :
[
{
"name": "xxx",
"aliases": ["x", "xx", "xxx"],
"unique_id": 1,
/* [...] */
},
/* [...] */
]
You can then do something like this :
const queryParam = /*search query*/;
const arr = /* get the JSON record */;
const IDs = arr
.filter( entry =>(entry.aliases.includes(queryParam) || queryParam===entry.name) )
.map(entry=>entry.uniqueId);
This will give you an array of IDs which are potential matches.
If you need either 0 or 1 result only :
const ID = IDs[0] || null;
This will simply retrieve the first matched ID if there's one, otherwise it will set ID to null.
NB:
If you use an object of objects instead of an array of object, there's just a little bit of modifications to do (mainly using Object.entries) but it still is trivial.
PS:
I would recommend to always add the full name in the aliases, this will ease the filtering part (no || would be required).

Trying to loop through JSON file

I am creating a dictionary app in React, I have loaded in the JSON dictionary which looks like this:
{
"DIPLOBLASTIC": "Characterizing the ovum when it has two primary germinallayers.",
"DEFIGURE": "To delineate. [Obs.]These two stones as they are here defigured. Weever.",
"LOMBARD": "Of or pertaining to Lombardy, or the inhabitants of Lombardy.",
"BAHAISM": "The religious tenets or practices of the Bahais.",
"FUMERELL": "See Femerell."
}
The user enters a word in the input field and the value is then passed into the following function to search for a matching key in the JSON. Matching words are then pushed into an array of results with their respective value.
handleSearch: function(term) {
var term = term;
var results = [];
for (var key in Dictionary) {
if (Dictionary.hasOwnProperty(key)) {
if (term == Dictionary[key]) {
results.push(Dictionary[key])
}
}
}
console.log(results)
},
However I am struggling to find a successful way of looping through it to get results. the console is logging an empty array.
Can anyone please suggest where I am going wrong?
You can have better matching by adding a compare function (in example below it is the compareTerm function). What I did there is comparing if the term STARTS with the dictionary key, if you want it to be any part of the string you can change it from === 0 to > -1.
// compare function which needs to be added somewhere
function compareTerm(term, compareTo) {
var shortenedCompareTo = compareTo
.split('')
.slice(0, term.length)
.join('');
return term.indexOf(shortenedCompareTo.toLowerCase()) === 0;
}
// only changed the compare function
handleSearch: function(term) {
var results = [];
for (var key in Dictionary) {
if (Dictionary.hasOwnProperty(key)) {
if (compareTerm(term, Dictionary[key])) {
results.push(Dictionary[key])
}
}
}
console.log(results);
},

Optional search parameters with mongoose?

I'm an inexperienced web developer and I'm having trouble with making an API.
This API should be able to take these parameters; all parameters should be optional (which are title, categories) and I should be able to limit the number of results I get i.e. where to start the results and how many results I should return.
app.get('/images', function(req, res) {
// var searchKey = req.query.keyword;
console.log("hello!");
var regex = new RegExp(req.query.q, 'i');
return Image.find({
title: regex
},function(err, q) {
console.log("do this");
return res.send(q);
});
});
For example, say we have 10 images with title "Cats A", "Cats B", etc and categories as empty ( [ ] ). We then want start from result 3 and display 6 results.
This is my code, and I'm not sure how to add the extra functionalities in.
You can build up your query as needed based on the supplied parameters. I'm guessing a bit with how the parameters are provided, but here's an example:
// Build up the query conditions based on the supplied parameters (if any).
var conditions = {};
if (req.query.q) {
// Match the query string against the either the title or categories fields
var regx = new RegExp(req.query.q, 'i');
conditions.$or = [
{title: regx},
{categories: regx}
];
}
var query = Image.find(conditions);
// Support optional skip and limit parameters.
if (req.query.skip) {
query = query.skip(req.query.skip);
}
if (req.query.limit) {
query = query.limit(req.query.limit);
}
// Execute the assembled query.
return query.exec(function(err, q) {
console.log("do this");
return res.send(q);
});

How to improve my backbone.js search Function?

I have a search function as part of a backbone app that I'm writing. I'd like some help expanding it out. Ideally I'd like it to be able to
search more than one category in my model and
not have to be such an exact match (perhaps using RegEx?)
Here's my code:
search: function(e) {
var search = this.$('.search').val(); //pulling in from the search bar
results = namesCollection.filter(function(item) { return item.get('First_Name') == (search);}); //returns a filtered collection that matches (exactly) the search results
filteredCollection.reset(results); //this just resets the current view
}
The code works, but right now it only returns results for an exact match on First_Name. Is there any way to have it match both First_Name and Last_Name? Also I'm trying to find a way to have it return for incomplete searches. So that entering 'Joh' in the search bar, would return a First_Name of John and Johanna.
Here's what my data looks like (simplified, of course):
var data = [
{
"First_Name": "John",
"Last_Name": Smith
},
{
"First_Name": "Johanna",
"Last_Name": "Greene"
}
];
And namesCollection refers to a backbone collection of all the names in my data set. Thanks!
As for the searching first and last names why not just run another filter on your filtered results? You could split the search by spaces.
results = namesCollection.filter(function(item) { return item.get('First_Name') == (search.split(' ')[0]);});
if(search.split(' ').length > 1){
results = namesCollection.filter(function(item) { return item.get('Last_Name') == (search.split(' ')[1]);});
}
As for finding a similar string that might work with mispelled words you are probably going to need something like a Levenshtein function which allows you to calculate the similarity between to strings. You could then determine based on your own threshold whether or not to consider it a match. Here is a js library for it
If you want to do partial matches as well assuming they are correctly spelled you could first search for exact matches and if one is found use it (let's say for the first name which means there is only one element after split). If an exact match is not found then try a partial match with an indexOf(). If you get a match on the first name and there is also a last name (meaning there are more than one elements in the split) then attempt an exact match of the last name. If that last name match fails then do the partial match search.
I would leverage lodash/underscore. Makes life easy. You can probably deconstruct to native js, but I find this easier.
#!/usr/bin/env node
_ = require('lodash');
var search = 'john';
var data = [
{
"First_Name": "John",
"Last_Name": "Smith"
},
{
"First_Name": "Jessica",
"Last_Name": "Greene"
},
{
"First_Name": "Sam",
"Last_Name": "Johnson"
}
];
var re = new RegExp(search, 'i');
data = data.filter(function(model){
var matched = false;
_.each(_.values(model), function(val){
if ( re.test(val) ) {
matched = true;
}
});
return matched;
});
console.log(data);
Outputs:
[ { First_Name: 'John', Last_Name: 'Smith' },
{ First_Name: 'Sam', Last_Name: 'Johnson' } ]
To work off a backbone collection you need to do this.collection.filter and also use model.attributes for the _.values(model.attributes, cb). assuming its a flat object.
This would of course match any value in the object, and I did it in node, but would easily run in backbone/browser.
I am not too familiar with Backbone, but what about changing the exact matching to a .indexOf or .contains? That way it can filter while you type in the keyword and so on keyup you can move to a more exact matching, the more keywords you give..
This is for instance the system that shuffle.js uses. Have a look at how that search works, might be what you are searching for i think.
search: function(e) {
var search = this.$('.search').val(); //pulling in from the search bar
results = namesCollection.filter(function(item) { return item.get('First_Name').indexOf( search ) !== -1 }); //returns a filtered collection that matches (not exactly) the search results
filteredCollection.reset(results); //this just resets the current view
}

Categories

Resources