Javascript find if english alphabets only - javascript

Am trying to find some text only if it contains english letters and numbers using Javascript/jQuery.
Am wondering what is the most efficient way to do this? Since there could be thousands of words, it should be as fast as possible and I don't want to use regex.
var names[0] = 'test';
var names[1] = 'हिन';
var names[2] = 'لعربية';
for (i=0;i<names.length;i++) {
if (names[i] == ENGLISHMATCHCODEHERE) {
// do something here
}
}
Thank you for your time.

A regular expression for this might be:
var english = /^[A-Za-z0-9]*$/;
Now, I don't know whether you'll want to include spaces and stuff like that; the regular expression could be expanded. You'd use it like this:
if (english.test(names[i])) // ...
Also see this: Regular expression to match non-English characters?
edit my brain filtered out the "I don't want to use a regex" because it failed the "isSilly()" test. You could always check the character code of each letter in the word, but that's going to be slower (maybe much slower) than letting the regex matcher work. The built-in regular expression engine is really fast.
When you're worried about performance, always do some simple tests first before making assumptions about the technology (unless you've got intimate knowledge of the technology already).

If you're dead set against using regexes, you could do something like this:
// Whatever valid characters you want here
var ENGLISH = {};
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("").forEach(function(ch) {
ENGLISH[ch] = true;
});
function stringIsEnglish(str) {
var index;
for (index = str.length - 1; index >= 0; --index) {
if (!ENGLISH[str.substring(index, index + 1)]) {
return false;
}
}
return true;
}
Live Example:
// Whatever valid characters you want here
var ENGLISH = {};
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split("").forEach(function(ch) {
ENGLISH[ch] = true;
});
function stringIsEnglish(str) {
var index;
for (index = str.length - 1; index >= 0; --index) {
if (!ENGLISH[str.substring(index, index + 1)]) {
return false;
}
}
return true;
}
console.log("valid", stringIsEnglish("valid"));
console.log("invalid", stringIsEnglish("invalid!"));
...but a regex (/^[a-z0-9]*$/i.test(str)) would almost certainly be faster. It is in this synthetic benchmark, but those are often unreliable.

Iterate each character in the string and check if the key code is not between 65 and 122, which are the Latin alphabet, lowercase and uppercase.
If wished to add punctuations characters, add their keyCode to the check.
function isLatinString(s) {
var i, charCode;
for (i = s.length; i--;) {
charCode = s.charCodeAt(i)
if (charCode < 65 || charCode > 122)
return charCode
}
return true
}
// tests
[
"abxSDSzfgr",
"aAzZ123dsfsdfעחלעלחי",
"abc!",
"$abc",
"123abc",
" abc"
]
.forEach(s => console.log( isLatinString(s), s ))
Another way, using an explicit whitelist string to allow specific charatcers:
function isLatinString(s){
var c, whietlist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for( c in s ) // get each character in the argument string
// if whitelist string doesn't include the character, break
if( !whietlist.includes(s[c].toUpperCase()) )
return false
return true
}
// tests
[
"abCD",
"aAאב",
"abc!",
"$abc",
"1abc",
" abc"
]
.forEach(s => console.log( isLatinString(s), s ))

Using regex is the fastest way to do this I'm afraid. This to my knowledge should be the fastest algorithm:
var names = 'test',
var names[1] = 'हिन';
var names[2] = 'لعربية';
//algorithm follows
var r = /^[a-zA-Z0-9]+$/,
i = names.length;
while (--i) {
if (r.test(names[i])) {
// do something here
}
}

You should consider words that may contain special characters. For example {it's}, isn't it english?

Related

How can I create a pallindrome code in JavaScript?

So I am trying to create a code for palindrome this is how I tried. Is there another or better way of doing it?
But now it only shows that if the first value is equal or not and shows true or false?
var inpo= prompt("Please enter to check if palindrome")
var inp = parseFloat(inpo)
var a = inpo.split('')
var inpo2 = a.reverse()
var len= inpo.length
for (var i =0;i< len ;i++) {
if (inpo[i] == inpo2[i] )
alert("True")
else
alert("False")
}
A way to check if a word or an entire phrase is a palindrome or not:
function isPalindrome(str) {
// Escape the string: Eliminate punctuation and spaces, enforce lower case
let escaped = str.replace(/[^A-Za-z0-9_]/g,"").toLowerCase();
// Reverse the escaped string
let reversed = escaped.split('').reverse().join('');
//compare
return escaped == reversed;
}
console.log(isPalindrome('Level'));
console.log(isPalindrome('Red rum, sir, is murder'));
I hope the comments serve well as an explanation.
Also, you have a prompt example in THIS jsfiddle.
If you are creating a palindrome checker code, here is a simple way to do it. Split, reverse then join.
str1 = "xxaa";
str2 = str1.split('').reverse().join("");
if (str1 == str2) {
alert("good");
} else {
alert("not");
}
You can check the single character from the string consuming 1 character from right and another from left until you will find either the string is finished or there are 2 inequal character. I implemented with a classical for loop.
Note that bracket notation for strings [] is only recently supported, you can use charAt if memory serves me right
let inp = "otdto";
console.log(isPalindrome(inp));
function isPalindrome(inp) {
const len = inp.length;
for (let i = 0; i < Math.floor(len / 2); i++)
if (inp[i] != inp[len - i - 1])
return false;
return true;
}

Finding characters of a word in a string, optimized

I am doing doing a few code challenges in the hope to learn some new stuff. Currently I have written a piece of code that find charachter of a given word in a string of random letters.
I thought regexp might be the best performance-wise (it's one of the objectives). This code passes the checks but takes too long with absurd long strings. Is there any way I can improve this? It's really ugly as is honestly. I've tried several approaches but I am probably just really a newbie at reg exp etc.
before all the if statements I only used regexp but if str2 which is the word I am looking for had double characters it would come back 'true' because it would count already counted characters. That is why I am using replace to exclude them. That's all I could get.
the goal is to return true if a portion of str1 can be rearranged to form str2, otherwise return false. Only lower case letters will be used (a-z). No punctuation or digits will be included. for example scramble('aabbcamaomsccdd','commas') should return true
function scramble (str1, str2)
{
var o = 0; // tracks amount of matched letters.
for(i = 0; i < str2.length; i++)
{
var regex1 = new RegExp (str2[i]) ; // select letter from word that needs to be found
if( regex1.test(str1) == true)// if selected character is found us replace to remove it from the random characters string for next iteration.
{
str1 = str1.replace(regex1 ,"");
o++; // increment o if character is removed from random string.
}
}
//check if amount of removed characters equals total characters of word that we want.
if ( o == str2.length)
{
return true
}
if (o !== str2.length)
{
return false
}
}
Update: I flagged the hash table as answer because afaik this was not doable with regexp it seems also I was able to achieve a proper result with .split and loops myself plus the hash table also achieved this.
if-less methodology!
i didnt stress it on tests but looks fine
function scramble(str1, str2) {
str1 = [...str1];
return [...str2].filter((str => (str == str1.splice(str1.indexOf(str), 1)))).join('') == str2;
}
You could take a hash table, count the wanted characters and return if no count is not more necessary.
function scramble (str1, str2) {
var counter = {},
keys = 0;
for (let i = 0; i < str2.length; i++) {
if (!counter[str2[i]]) {
counter[str2[i]] = 0;
keys++;
}
counter[str2[i]]++;
}
for (let i = 0; i < str1.length; i++) {
if (!counter[str1[i]]) continue;
if (!--counter[str1[i]] && !--keys) return true;
}
return false;
}
console.log(scramble('abc', 'cba'));
console.log(scramble('abc', 'aba'));
console.log(scramble('abcdea', 'aba'));
console.log(scramble('aabbcamaomsccdd', 'commas'));

Find letters in random string exactly, using RegEx

The emphasis here is on the word exactly. This needs to work for any number of permutations, so hopefully my example is clear enough.
Given a string of random letters, is it possible (using RegEx) to match an exact number of letters within the given string?
So if I have a string (str1) containing letters ABZBABJDCDAZ and I wanted to match the letters JDBBAA (str2), my function should return true because str1 contains all the right letters enough times. If however str1 were to be changed to ABAJDCDA, then the function would return false as str2 requires that str1 have at least 2 instances of the letter B.
This is what I have so far using a range:
const findLetters = (str1, str2) => {
const regex = new RegExp(`[${str2}]`, 'g')
const result = (str1.match(regex))
console.log(result)
}
findLetters('ABZBABJDCDAZ', 'JDBBAA')
As you can see it matches the right letters, but it matches all instances of them. Is there any way to do what I'm trying to do using RegEx? The reason I'm focusing on RegEx here is because I need this code to be highly optimised, and so far my other functions using Array.every() and indexOf() are just too slow.
Note: My function only requires to return a true/false value.
Try (here we sort letters of both strings and then create regexp like A.*A.*B.*B.*D.*J)
const findLetters = (str1, str2) => {
const regex = new RegExp([...str2].sort().join`.*`)
return regex.test([...str1].sort().join``)
}
console.log( findLetters('ABZBABJDCDAZ', 'JDBBAA') );
console.log( findLetters('ABAJDCDA', 'JDBBAA') );
I dont know if regex is the right way for this as this can also get very expensive. Regex is fast, but not always the fastest.
const findLetters2 = (strSearchIn, strSearchFor) => {
var strSearchInSorted = strSearchIn.split('').sort(function(a, b) {
return a.localeCompare(b);
});
var strSearchForSorted = strSearchFor.split('').sort(function(a, b) {
return a.localeCompare(b);
});
return hasAllChars(strSearchInSorted, strSearchForSorted);
}
const hasAllChars = (searchInCharList, searchCharList) => {
var counter = 0;
for (i = 0; i < searchCharList.length; i++) {
var found = false;
for (counter; counter < searchInCharList.length;) {
counter++;
if (searchCharList[i] == searchInCharList[counter - 1]) {
found = true;
break;
}
}
if (found == false) return false;
}
return true;
}
// No-Regex solution
console.log('true: ' + findLetters2('abcABC', 'abcABC'));
console.log('true: ' + findLetters2('abcABC', 'acbACB'));
console.log('true: ' + findLetters2('abcABCx', 'acbACB'));
console.log('false: ' + findLetters2('abcABC', 'acbACBx'));
console.log('true: ' + findLetters2('ahfffmbbbertwcAtzrBCasdf', 'acbACB'));
console.log('false: ' + findLetters2('abcABC', 'acbAACB'));
Feel free to test it's speed and to optimize it as I'm no js expert. This solution should iterate each string once after sorting. Sorting is thanks to https://stackoverflow.com/a/51169/9338645.

Multiple ip addresses in single string

I have that kind of datas :
172.12.1.3;185.16.6.13;...
And sometimes the submask so it could be :
172.12.1.3;185.16.6.13/32;172.12.1.4;...
So I wanted to use regex (in js) to be sure each ip address is correct using ";" as separator.
It should not be too difficult, but even with a few research i've just manage to do something like this :
/^(((^|\.?)(1[0-9]{2}|[1-9][0-9]|[0-9]|2[0-4][0-9]|25[0-5])){4}(\;|$))*$/
Btw I know that I should, but I'm not really into regex...
Can someone give me a hand please ?
edit :
So i've tried something like this :
var poolIp = v.split(";");
var ipAddress = /^(((^|\.?)(1[0-9]{2}|[1-9][0-9]|[0-9]|2[0-4][0-9]|25[0-5])){4}(\;|$))*$/;
var ret = true;
for (var i = 0; i < poolIp.length; i++) {
var matches = ipAddress.exec(poolIp[i]);
if (!matches) {
ret = false;
}
}
return ret;
And it's way better, but ip address with submask is not valid and ip with 3 digits are valid.
You may use the following function to validate such strings of IP addresses. Note that the port number validation can be enhanced, I just check if the value is numeric.
function checkIsIPV4s(entry) {
var ips = entry.split(';'); // Split into separate IPs
for (var ip of ips) {
var blocks = ip.split(/[.\/]/); // Split with dot and slash
if(blocks.length === 5) { // If there are 5 blocks,
var last = blocks.pop(); // remove the last one
if (!/^\d+$/.test(last)) { // and check if it is numeric
return false; // if not - FALSE
}
}
if(blocks.length === 4) { // If block number is 4
var res = blocks.every(function(block) { // check each part
return parseInt(block,10) >=0 && parseInt(block,10) <= 255;
});
if (!res) {return false; } // If any part is not in 0..255 - FALSE
} else {
return false; // If block number is not 4 - FALSE
}
}
return true;
}
var str = "172.12.1.3;185.16.6.13/32;172.12.1.4;255.255.255.255";
console.log(checkIsIPV4s(str));
str2 = "172.12.1.34444;185.16.6.13/32";
console.log(checkIsIPV4s(str2));
However, there is a way to use a huge and unreadable regex, too. Adding this just to show that it is possible to do it with a regex:
/^(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)?(?:;(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)?)*$/
See the regex demo
The pattern matches:
^ - start of string
(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)? - a single IP pattern (all up to (?:\/\d+)?) with an optional port number ((?:\/\d+)?)
(?: - the non-capturing group start
; - the separator
(?:(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))\.){3}(?:\d{1,2}|1\d{2}|2(?:[0-4]\d|5[0-5]))(?:\/\d+)? - the single IP pattern, same as above
)* - 0 or more occurrences of the non-capturing group sequences
$ - end of string.
This should do it:
var re = /^(;?[1-9][\d]{1,2}(\.[\d]{1,3}){3}(\/[\d]{1,3})?)+$/
re.test('172.12.1.3;185.16.6.13/32;172.12.1.4') // true
re.test('172.12.1.3;185.16.6.13/32;172.12.1') // false
re.test('072.12.1.3;185.16.6.13/32;172.12.1.4') // false
Or splitting them up:
var re = /^[1-9][\d]{1,2}(\.[\d]{1,3}){3}(\/[\d]{1,3})?$/
var ip1 = '172.12.1.3;185.16.6.13/32;172.12.1.4'.split(';');
var ip2 = '172.12.1.3;185.16.6.13/32;172.12.1'.split(';');
var ip3 = '072.12.1.3;185.16.6.13/32;172.12.1.4'.split(';');
ip1.every((ip) => re.test(ip));
ip2.every((ip) => re.test(ip));
ip3.every((ip) => re.test(ip));
You can use http://regexr.com/ to test your regexp, and read about Array.every here.

Look for various substrings and return the position of the one found

I want to analize a string for a substring and return the position of the substring if it was found.
function analize(t) {
if (t.indexOf(" a ") > -1 || t.indexOf(" b ") > -1 || t.indexOf(" c ") > -1) {
alert(t.indexOf(" a "));
}
The problem is that I'm looking for more than one substring and I cant echo its position since I don't know which was found. While this example only has 3 strings, I need to do it with a lot more in my code. How can I check for various items and return the position of the one that's found?
Use a regular expression with String.search:
var position = t.search(/ a | b | c /);
This is easy enough to code up if your list of strings is constant. But if your list is dynamic, you'd have to build the regular expression programmatically. You can do so like this:
var searchStrings = [" a ", " b ", " c "].map(function (item) {
return item.replace(/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); // escape RegEx meta chars
});
var position = t.search(new RegExp(searchStrings.join("|")));
Note that I used Array.map() above. This will not work by default in older browsers. You have to add it in manually. See the compatibility notes for an implementation you can use to get this functionality in older browsers.
Use the following to return the position of the first match:
function indexOfAny(strs, s) {
for (var i = 0; i < strs.length; i++) {
var ind = s.indexOf(strs[i]);
if (ind != -1)
return ind;
}
return -1;
}
indexOfAny(["a", "b", "c"], "test-b-stri-c-ng");
Returns:
5
just put the strings you look for in an array then use the for-in loop to go through each one and output the position if found.
function analyze(t) {
var strings = ["a","b","c"...];
for(index in strings])
if(t.indexOf(string[index]) > -1)
alert(t.indexOf(" a "));
}

Categories

Resources