Using RegExp to loop through arrays instead of for loops (Javascript) - javascript

I have the below code which works. But would using RegExp be a more efficient code?
(Return true if the string in the first element of the array contains the letters of the string in the second element of the array.)
function mutation(arr) {
var first = arr[0].split("");
var second = arr[1].split("");
var answer = false;
for (var e = 0; e < second.length; e++) {
answer = false;
for (var i = 0; i < first.length; i++) {
if (first[i] === second[e]) {
answer = true;
}
}
}
return answer;
}
mutation(['hello', 'hey']);

Using regex to do this check as the code you've shown above:
var a = 'hello how are you';
var b ='hey you there';
var result = new RegExp(b.split(/ +/)[0].split('').join('|')).test( a.split(/ +/)[0] );
//=> true
First split(/ +/)[0] is used to get first word from both strings
Then split('') is used to get each letter from first word of 2nd input
join('|') is used to join them by | to get regex as h|e|y
new RegExp is used for construct a regex object
test is used to execute the regex

In ES6 it can be written as follows:
function mutation(lettersSource, checkedString) {
var referenceLetters = new Set(lettersSource); // get letters from string
var usedLetters = new Set(checkedString);
// create union of letters in both strings
var lettersUnion = new Set([...usedLetters, ...referenceLetters]);
return lettersUnion.size === referenceLetters.size;
}
This solution is O(m+n+k) where m and n is number of letters in strings, and k is number of used letters.
Your solution is O(m*n), quite inefficient.
In ES5 Object can be used as well as dictionary to collect only letters, but it will be slower for many possible letters (Unicode strings).
If you don't have to care about memory usage, you can create dense array using .charCodeAt to index elements in array for O(1) access to checking if elements exists (O(m+n+k)).

Related

Iterate through an array and convert all character codes to characters?

I've coded myself into a hole and though it would be easier to start again, there is still a lesson to be learned here (it's just practice anyway).
I'm building a caesar cipher which will accept two parameters: the message, and the cipher key. Each letter is compared to its corresponding letter in the cipher key, then changed to a new character code.
I'm having a hell of a time figuring out how to turn an array of character codes into an array (or better yet, a string) of characters.
Here's my code:
function cipher(message, cipherKey) {
//convert the message and cipher key to arrays of their character codes
var messageArr = message.toLowerCase().split("").map(x => x.charCodeAt() - 97);
var cipherKeyArr = cipherKey.toLowerCase().split("").map(x => x.charCodeAt() - 97);
//create new array for the ciphered array, which will turn back to a string
var cipheredArr = [];
//loop through both the cipher key value and message key value to
//create the ciphered array
for (var i = 0; i < messageArr.length; i++) {
cipheredArr[i] = messageArr[i] + cipherKeyArr[i];
if (cipheredArr[i] >= 26) {}
}
//go through the ciphered array and make it loop back through
//the alphabet once it goes past z
for (var i = 0; i < cipheredArr.length; i++) {
if (cipheredArr[i] >= 26) {cipheredArr[i] = cipheredArr[i] - 26;}
}
//display on webpage
return cipheredArr;
}
So the cipheredArr is an array of numbers (character codes) but I can't find a good way to iterate through it and change them back into letters. The .fromCharCode() syntax is confusing me for this purpose.
To get an array of characters for an array of character codes, use map:
var chars = codes.map(code => String.fromCharCode(code));
(Note: Just codes.map(String.fromCharCode) won't work, String.fromCharCode would make inappropriate use of the second and third arguments map passes the callback.)
To get a string from those codes:
// ES2015+
var str = String.fromCharCode(...codes);
// ES5 and earlier:
var str = String.fromCharCode.apply(null, codes);
fromCharCode returns a string made up of the code units you pass it as discrete arguments (MDN | spec).

having an issue w/ .split in a JavaScript function that gets the max # of repeating chars per word in a string

I'm writing a JavaScript function that has to take in a string argument & determine the word or words with the maximum number or repeated (or most frequent) non sequential characters and return that word or words.
The way that I went about solving this problem was to first find the maximum number of times a character was repeated per word and record that number to use later in a function to test against every word in the string (or the array of strings as I later split it); if the word met the conditions, it's pushed into an array that I return.
My maxCount function seemed to work fine on its own but when I try to make it work together with my other function to get the words with max repeated chars returned, it's not working in JS Fiddle - it keeps telling me that "string.split is not a function" - I'll admit that the way I'm using it (string.split(string[i]).length) to analyze words in the string letter by letter is a bit unconventional - I hope there's some way to salvage some of my logic to make this work in the functions that can work together to get the results that I want.
Also, I don't know if I'm using Math.max correctly/in a "legal" way, I hope so. I've tried switching my variable name to "string" thinking that would make a difference but it did not even though my arguments are of the string variety and it's a string that's being represented.
Here's a link to my Fiddle:
https://jsfiddle.net/Tamara6666/rdwxqoh6/
Here's my code:
var maxCount = function (word) {
/// var maxRepeats = 0;
var numArray = [];
var string = word;
for (var i = 0, len = string.length; i < len; i++) {
//split the word('string') into letters at the index of i
numArray.push((string.split(string[i]).length) -1);
}
var max = Math.max(...numArray);
return max;
}
///console.log(maxCount("xxxxxxxxxxxxx"));
var LetterCount = function(string){
var repeatedChars = 0;
var wordArray=[];
var stringArray = string.split(" ");
for (var i = 0; i < stringArray.length; i++){
var eachWord = stringArray[i];
var maxRepeats = maxCount(stringArray);
if (repeatedChars < maxRepeats) {
repeatedChars = maxRepeats;
wordArray = [eachWord];
}else if (repeatedChars == maxRepeats) {
wordArray.push(eachWord);
}
}
return wordArray;
};
console.log(LetterCount("I attribute my success to cats"));
//should return ["attribute", "success"]
*** I've tried to map this first function onto the array formed when I split my string at the spaces but it is just returned me an empty array (I also might not have been using map correctly in this example); I also have tried using valueOf to extract the primitive value out of the array from the first function which also didn't work. I'm not really sure what to do at this point or what angle to take- I feel if I understood more what was going wrong I could more easily go about fixing it. Any help would be much appreciated. Thanks!
You are passing an array to maxCount at line 20, while it expects a string:
var maxRepeats = maxCount(stringArray);
You should use:
var maxRepeats = maxCount(eachWord);
If you are getting split is not a function error then first make sure that your string isn't null by printing it on console. If it isn't null then confirm that its a string not an array or some other thing.

JavaScript reverse the order of letters for each word in a string

I am trying to get around the following but no success:
var string = 'erehT era a tsav rebmun fo secruoser rof gninrael erom tpircsavaJ';
var x = string.split(' ');
for (i = 0; i <= x.length; i++) {
var element = x[i];
}
element now represents each word inside the array. I now need to reverse not the order of the words but the order of each letter for each word.
var string = "erehT era a tsav rebmun fo secruoser rof gninrael erom tpircsavaJ";
// you can split, reverse, join " " first and then "" too
string.split("").reverse().join("").split(" ").reverse().join(" ")
Output: "There are a vast number of resources for learning more Javascript"
You can do it like this using Array.prototype.map and Array.prototype.reverse.
var result = string.split(' ').map(function (item) {
return item.split('').reverse().join('');
}).join(' ');
what's the map function doing there?
It traverses the array created by splitting the initial string and calls the function (item) we provided as argument for each elements. It then takes the return value of that function and push it in a new array. Finally it returns that new array, which in our example, contains the reversed words in order.
You can do the following:
let stringToReverse = "tpircsavaJ";
stringToReverse.split("").reverse().join("").split(" ").reverse().join(" ")
//let keyword allows you declare variables in the new ECMAScript(JavaScript)
You can do the following.
var string = "erehT era a tsav rebmun fo secruoser rof gninrael erom tpircsavaJ";
arrayX=string.split(" ");
arrayX.sort().reverse();
var arrayXX='';
arrayX.forEach(function(item){
items=item.split('').sort().reverse();
arrayXX=arrayXX+items.join('');
});
document.getElementById('demo').innerHTML=arrayXX;
JavaScript split with regular expression:
Note: ([\s,.]) The capturing group matches whitespace, commas, and periods.
const string = "oT eb ro ton ot eb, taht si a noitseuq.";
function reverseHelper(str) {
return str.split(/([\s,.])/).
map((item) => {
return item.split``.reverse().join``;
}).join``;
}
console.log(reverseHelper(string));

Javascript - best way to parse custom tags [duplicate]

This question already has answers here:
XML parsing of a variable string in JavaScript
(10 answers)
Closed 9 years ago.
I wrote an API that returns the following
<location><lat>41.47033705</lat><lon>-81.93612862</lon></location>
<location><lat>41.470320224762</lat><lon>-81.9364535808563</lon></location>
<location><lat>41.4704650640488</lat><lon>-81.9449239969254</lon></location>
<location><lat>41.4780235290527</lat><lon>-81.8454140424728</lon></location>
<location><lat>41.48597253</lat><lon>-81.82579113</lon></location>
I have an AJAX call that gets this and now I need to use it in my JavaScript.
Ultimately I would like and 2d Array [lat,lon]
What is the least amount of code to do this?
Assuming the response is valid XML, you can use getElementsByTagName and push to an array:
var arr = [];
for (var location in response.getElementsByTagName('location'))
{
arr.push([
parseFloat(location.getElementsByTagName('lat')[0]),
parseFloat(location.getElementsByTagName('lon')[0])
]);
}
You can make your AJAX call via XmlHttmlRequest and get responseXML. Then you can parse your data via XmlDocument method and properties.
You can even run Xpath queries on the result to select exactly what you need.
Just use JQuery's selector engine to parse your code.
Wrap your elements in a <div id="data"> ... </data> for easy selection and you can do the following:
var _locations = $('#data').find('location');
var my_data = [];
$.each(_locations, function(index, loc) {
var _lat = $(loc).find('lat');
var _lon = $(loc).find('lon');
my_data.push([_lat.text(), _lon.text()]);
})
// my_data will contain a 2D array of your lat, lon
GoodLuck
-Kiru
Regex 101 Demo
Regex
<lat>([^<]+)<\/lat><lon>([^<]+)<\/lon>
using g (global) flag
Description
<lat> Literal <lat>
1st Capturing group ([^<]+)
Negated char class [^<] 1 to infinite times [greedy] matches any character except:
< The character <
<\/lat><lon> Literal </lat><lon>
2nd Capturing group ([^<]+)
Negated char class [^<] 1 to infinite times [greedy] matches any character except:
< The character <
<\/lon> Literal </lon>
g modifier: global. All matches (don't return on first match)
Visualization
Taking the above to solve your specific issue
DEMO jsFiddle
JS
var text = " <location><lat>41.47033705</lat><lon>-81.93612862</lon></location><location><lat>41.470320224762</lat><lon>-81.9364535808563</lon></location><location><lat>41.4704650640488</lat><lon>-81.9449239969254</lon></location><location><lat>41.4780235290527</lat><lon>-81.8454140424728</lon></location><location><lat>41.48597253</lat><lon>-81.82579113</lon></location>";
var myregexp = /<lat>([^<]+)<\/lat><lon>([^<]+)<\/lon>/g;
var results = new Array();
var match = myregexp.exec(text);
while (match != null) {
var result = new Array();
for (var i = 1; i < match.length; i++) {
result.push(match[i]);
}
results.push(result);
match = myregexp.exec(text);
}
console.log(results);
the variable results contains a 2d array [lat, lon]

need a regular expression to search a matching last name

I have a javascript array which holds strings of last names.
I need to loop this array and separate out the last names which match a given string.
var names = ['woods','smith','smike'];
var test = 'smi';
var c = 0;
var result = new Array();
for(var i = 0; i < names.length; i++)
{
if(names[i].match(test))// need regular expression for this
result[c++] = names[i];
}
return result;
name should match the test string even if the test lies within the name. so... mik should match 'Mike' and 'Smike' also.
Any help is really appreciated!
You can create a regex from a string:
var nameRe = new RegExp("mik", "i");
if(names[i].match(nameRe))
{
result.push(names[i]);
}
Make sure to escape regex meta-characters though - if your string may contain them. For example ^, $ may result in a miss-match, and *, ? ) and more may result in an invalid regex.
More info: regular-expressions.info/javascript
You can do this without regex:
if (names[i].toLowerCase().indexOf(test.toLowerCase()) >= 0)
// ...
Javascript string .search is what you're looking for.. You don't even need regex although search supports that too.
var names = ['woods','smith','smike'];
var test = 'smi';
var c = 0;
var result = new Array();
for(var i = 0; i < names.length; i++)
{
if(names[i].toLowerCase().search(test))// need regular expression for this
result.push(names[i]);
}
return result;
You can do this with one regex.
var r = new RegExp(names.join('|'), "igm");
'woods smith'.match(r);
You don't need regex for this, so I'd recommend using string manipulation instead. It's almost (almost!) always better to use string functions instead of regex when you can: They're usually faster, and it's harder to make a mistake.
for(var i = 0; i < names.length; i++)
{
if(names[i].indexOf(test) > -1)
//match, do something with names[i]...
}

Categories