How to iterate through multiple lines of input like a matrix, etc.? - javascript

I recently started HackerRank and throughout the problems, I've noticed that they often use multiple lines for the input. For example, for the Day 6: Let's Review challenge, the sample input is
2
Hacker
Rank
which is referred to as a string. I want to know if there is a way to iterate by line instead of individual character. This format throws me off on a lot of the exercises, and I want to know if there is a way to make this easier.

You can split() the string by \n
let str = `2
Hacker
Rank`
str = str.split('\n');
str.forEach(x => {
console.log(x);
})

You can use `` to write multiple lines string in Javascript

Related

JavaScript - Dynamic RegExp for Duplicate Characters

I'm very new to programming, and I'm trying to solve an exercise where you encode a string (in this case, a single word) based on whether or not the constituent characters occur twice or more. Characters occurring only once encode to, say "■", characters encoding twice or more encode to, say "X".
Example: input = "hippodrome" :: output = "■■XXX■■X■■"
I managed to solve it in a very convoluted way using nested loops and a key:value object storing character:occurrences, but i am trying to refactor the solution to be more efficient using a dynamically created RegExp, but i think i'm not understanding regex notation.
function encodeDupes(word) {
let encoded = "";
for (let char of word) {
let regex = new RegExp(char + "{2,}","ig"); // create a regex to see if "char" occurs 2 or more times
regex.test(word) ? encoded += "X" : encoded += "■"; // check this char against rest of word, push appropriately
}
return encoded;
}
it works with a more simple gate like char < "m" ? do X : do Y, and i thought i understood this answer here ({n,} = at least n occurrences), but i'm new enough that i'm still not sure if it's my regex or my logic.
thank you!
I'm very new to programming, ..., I am trying to refactor the solution to be more efficient using a dynamically created RegExp...
That's a bit of a catch 22 because regular expressions trade efficiency for convenience. In order for the regular expression "engine" to run, a grammar must be established, and a lexer, parser, and evaluator transform the string-based input expressions into program output. It's (sometimes) convenient to implement a particular program using regular expressions, but it's almost impossible to beat out a fundamental algorithm that isn't slowed down by the regular expression engine.
I managed to solve it in a very convoluted way using nested loops and a key:value object storing character:occurrences ...
Convoluted indeed, but sadly not uncommon to see even "expert" programmers do such things. An efficient algorithm emerges when we realise we don't need to count each letter. Instead, we only need to know whether a letter occurs more than once. Using two Set objects, once and more, we can determine the answer without needing to allocate counter memory per letter! And sets are lightning fast, thanks to O(1) constant-time lookup -
function encodeDupes(word)
{ const once = new Set
const more = new Set
for (const c of word)
if (more.has(c))
continue
else if (once.has(c))
(once.delete(c), more.add(c))
else
once.add(c)
return Array
.from(word, c => more.has(c) ? "X" : "■")
.join("")
}
console.log(encodeDupes("hippodrome"))
Output
■■XXX■■X■■
Usually RegExp are used to compare entire words or phrases.
Whenever {n,} is used, it's searching for two or more characters consecutively. Here's an example:
n{2,}
nn # match
anna # match
nan # does not match
The following RegExp isn't perfect, but it should suffice, replacing n with the character of your choice
(.*n{2,}.*)|(.*n.*n.*)+
(.*n{2,}.*) —— for consecutive ‘n’s
| —— or
(.*n.*n.*)+ —— ‘n’s with anything in between
Let me know how it goes.

Regex Delimeter in PapaParse

I wish to ask, is it possible to use regexes as delimiters in PapaParse? Something like:
Papa.parse(string,
{
delimiter:regex
}
);
I am trying to match a specific pattern of CSVs like so:
/([A-Za-z]{2}[0-9]+,?)/g
i.e. I want exactly 2 letters, any amount of numbers, and a comma (or not, in the case of the last element).
Since string.split has a wonderful habit of returning anything but null when nothing matches regex patterns, I was hoping that my answer would lie in PapaParse. If this is not possible, then I would do something more long winded, but hopefully I can be laz-... efficent this time. :)
Trying to do the following:
Papa.parse('ACB5,dsa',{delimiter:'[A-Za-z]{2}[0-9]+,?'});
Results in
["ACB5","dsa"]
Thank you for your time.
edit
Trying out the regex on regexr.com shows that it works with values like
AB544444444444,BC5,
aa5,
At this point, I realize that this was actually a dozy question, considering how a delimiter is the thing that separates what you want to break up.
I'm writing the longer winded version now, so I'll stick that up soon
As Matt (and common sense) rightly say, yes, The delimiter is just ye olde comma. I was looking for a way to separate the results based on a regex, which past me had thought would have some similarity to how string.split works. This is the snippet I was trying to shrink down.
var result = null;
var regex = /([A-Za-z]{2}[0-9]+,?)/g; //Any two letters, a number, and a space
$(document).ready( function() {
$('#inputGraphText').on('input', function(e){ //on text input...
result = $(this).val().split(','); //split using the complex delimiter ','. Also adds a few "" elements to the array for some reason.
var tidy = new Array();
result.forEach(function(elem){
if(elem.search(regex) > -1){
tidy.push(elem.replace('/[, ]/g',''));//Tidy up the result
}
});
$('#first').html(tidy); //place to print out the tidied results
})
});
Obviously , this is not terribly schnazzy (and completely misses out on using PapaParse), but it is what I originally set out to do.
Any better alternatives will take pride of place, but for now, this is fine.
My apologies for the confusion.

How to split a string with the help of JavaScript's regex?

I need to split a string to one or more substrings each of which contains no more or less than two dots. For example, if the string is foo.boo.coo.too" then what would be the regex to get the following array?: ["foo.boo.coo", "boo.coo.too"]. I hope there will be someone to answer this question - I will really admire you, as I've been programming for several years and have not still be used to regular expressions well enough to solve this particular problem by myself. Thank you very much in advance. Let me know your identity so that I can credit you as a contributor of the program I am creating.
RegEx is for this Problem not the best solution a similar problem was discussed here: split-a-sting-every-3-characters-from-back-javascript
A good javascript solution would be a javascript function like this
function splitter(text){
var parts = text.split(".");
var times = parts.length - 2;
var values = [];
for(var index = 0; index<times;index++)
{
values.push(parts.slice(index,index+3).join("."));
}
return values;
}
splitter("too.boo.coo.too")
//=> Result tested on Chrome 25+ ["too.boo.coo", "boo.coo.too"]
I hope this helps
If you want to Use Regex try the Lookhead Stuff, this could help http://www.regular-expressions.info/lookaround.html
Regex by its nature will return non-intersecting results, so if you want "all matches" from a single regex - it's not possible.
So basically you will need to find first match, and then start from next position to find next match and so on; something like this technique described here regex matches with intersection in C# (it's not JavaScript but idea is the same)
You can use the following regex for example:
(?<=^|\.)((?:[^.]*\.){2}[^.]*?)(?=$|\.)
It ensures that it starts and ends with dot, or at begin/end of line, and contains exactly two dots inside, and captures result in first capture. You can replace * with + to make sure at least one symbol exists between dots, if it is required.
But you need to understand that such approach has really bad performance for the task you are solving, so may be using other way (like split + for) will be better solution.

Regex extraction of one letter inside html chunk

Hi need to extract ONE letter from a string.
The string i have is a big block of html, but the part where i need to search in is this text:
Vahvistustunnus M :
And I need to get the M inside the nbsp's
So, who is the quickest regex-guru out there? :)
Ok, according to this page in the molybdenum api docs, the results will be all of the groups concatenated together. Given that you just want the char between the two 's then it's not good enough to match the whole thing and then pull out the group. Instead you'll need to do something like this:
(?<=Vahvistustunnus )[a-zA-Z](?= )
Warning
This might not work for you because lookbehinds (?<=pattern) are not available in all regex flavors. Specifically, i think that because molybdenum is a firefox extension, then it's likely using ECMA (javascript) regex flavor. And ECMA doesn't support lookbehinds.
If that's the case, then i'm gonna have to ask someone else to answer your question as my regex ninja (amateur) skills don't go much further than that. If you were using the regex in javascript code, then there are ways around this limitation, but based on your description, it sounds like you have to solve this problem with nothing but a raw regex?
Looks like it uses JavaScript and if so
var str = "Vahvistustunnus M :";
var patt = "Vahvistustunnus ([A-Z]) :";
var result = str.match(patt)[1];
should work.

Trying to remove trailing text

I having the following code. I want to extract the last text (hello64) from it.
<span class="qnNum" id="qn">4</span><span>.</span> hello64 ?*
I used the code below but it removes all the integers
questionText = questionText.replace(/<span\b.*?>/ig, "");
questionText=questionText.replace(/<\/span>/ig, "");
questionText = questionText.replace(/\d+/g,"");
questionText = questionText.replace("*","");
questionText = questionText.replace(". ",""); i want to remove the first integer, and need to keep the rest of the integers
It's the third line .replace(/\d+/g,"") which is replacing the integers. If you want to keep the integers, then don't replace \d+, because that matches one or more digits.
You could achieve most of that all on one line, by the way - there's no need to have multiple replaces there:
var questionText = questionText.replace(/((<span\b.*?>)|(<\/span>)|(\d+))/ig, "");
That would do the same as the first three lines of your code. (of course, you'd need to drop the |(\d+) as per the first part of the answer if you didn't want to get rid of the digits.
[EDIT]
Re your comment that you want to replace the first integer but not the subsequent ones:
The regex string to do this would depend very heavily on what the possible input looks like. The problem is that you've given us a bit of random HTML code; we don't know from that whether you're expecting it to always be in this precise format (ie a couple of spans with contents, followed by a bit at the end to keep). I'll assume that this is the case.
In this case, a much simpler regex for the whole thing would be to replace eveything within <span....</span> with blank:
var questionText = questionText.replace(/(<span\b.*?>.*?<\/span>)/ig, "");
This will eliminate the whole of the <span> tags plus their contents, but leave anything outside of them alone.
In the case of your example this would provide the desired effect, but as I say, it's hard to know if this will work for you in all cases without knowing more about your expected input.
In general it's considered difficult to parse arbitrary HTML code with regex. Regex is a contraction of "Regular Expressions", which is a way of saying that they are good at handling strings which have 'regular' syntax. Abitrary HTML is not a 'regular' syntax due to it's unlimited possible levels of nesting. What I'm trying to say here is that if you have anything more complex than the simple HTML snippets you've supplied, then you may be better off using a HTML parser to extract your data.
This will match the complete string and put the part after the last </span> till the next word boundary \b into the capturing group 1. You just need to replace then with the group 1, i.e. $1.
searched_string = string.replace(/^.*<\/span>\s*([A-Za-z0-9]+)\b.*$/, "$1");
The captured word can consist of [A-Za-z0-9]. If you want to have anything else there just add it into that group.

Categories