I'm asking you today for a little problem :
I have to live control capitalization/no capitalization with js on an input text field like this:
1st character of the entire string must be uppercase
1st character of each word (after space or hyphen) is free (lowercase or uppercase allowed)
All the nother characters must be lowercase
Desired Output: Grand-Father is Nice
I'm not a specialist of JS, i'm using split function, here is my code :
$('#name').on('input change',function() {
var arr1 = $(this).val().split(/[- ]/);
var result1 = "";
for (var x=0; x<arr1.length; x++)
result1+=arr1[x].substring(0,1)+arr1[x].substring(1).toLowerCase()+" ";
var res1 = result1.substring(0, result1.length-1);
var _txt = res1.charAt(0).toUpperCase() + res1.slice(1);
$('#name').val(_txt);
});
The script works but I would like to output the real delimiter found in string, even if it's a space " " or hyphen "-". Actually i can show only space. How can i solve it ?
Actual output: Grand Father is Nice
Any help would be appreciated.
Thank you!
User String.replace() with a RegExp and a callback.
If you know what are your delimiters, you can search for all characters that are no the delimiters, and format them:
var input = 'ègrand-Father is NièCe';
var d = '[^\s\-]'; // not space or dash
var result = input.replace(new RegExp('('+ d +')(' + d + '+)', 'g'), function(m, p1, p2, i) {
var end = p2.toLowerCase();
var start = i === 0 ? p1.toUpperCase() : p1;
return start + end;
});
console.log(result);
If the target browsers support it (Chrome does) or you use a transpiler, such as Babel (plugin), you can use Unicode property escapes in regular expressions (\p):
var input = 'ègrand-Father is NièCe';
var result = input.replace(/(\p{L})(\p{L}+)/gu, function(m, p1, p2, i) {
var end = p2.toLowerCase();
var start = i === 0 ? p1.toUpperCase() : p1;
return start + end;
});
console.log(result);
I'm not entirely sure what your aim is, but let's give it a shot.
This is how you can make all non-first letters be lowercase
let sentence = "this is wRoNg SenTEnce."
sentence.split(" ").map(word => word.charAt(0) + word.slice(1).toLowerCase()).join(" ")
This is how you can make first letter capital:
let sentence = "also Wrong sentence"
sentence.charAt(0).toUpperCase()
Related
I have to replace all letters of name on ****.
Example:
Jeniffer -> J****r
I try $(this).text( $(this).text().replace(/([^\w])\//g, "*"))
Also, if name is Ron -> R****n
You can use a regular expression for this, by capturing the first and last letters in a capture group and ignoring all letters between them, then using the capture groups in the replacement:
var updated = name.replace(/^(.).*(.)$/, "$1****$2");
Live Example:
function obscure(name) {
return name.replace(/^(.).*(.)$/, "$1****$2");
}
function test(name) {
console.log(name, "=>", obscure(name));
}
test("Ron");
test("Jeniffer");
But it's perhaps easier without:
var updated = name[0] + "****" + name[name.length - 1];
Live Example:
function obscure(name) {
return name[0] + "****" + name[name.length - 1];;
}
function test(name) {
console.log(name, "=>", obscure(name));
}
test("Ron");
test("Jeniffer");
Both of those do assume the names will be at least two characters long. I pity the fool who tries this on Mr. T's surname.
Since, you need to have four asterisk on each condition, you can create a reusable function that will create this format for you:
function replace(str){
var firstChar = str.charAt(0);
var lastChar = str.charAt(str.length-1);
return firstChar + '****' + lastChar;
}
var str = 'Jeniffer';
console.log(replace(str));
str = 'America';
console.log(replace(str))
Appears that you're looking for regex lookaround
Regex: (?<=\w)(\w+)(?=\w) - group 1 matches all characters which follow one character and followed by another one.
Tests: https://regex101.com/r/PPeEqx/2/
More Info: https://www.regular-expressions.info/lookaround.html
Find first and last chars and append **** to the first one and add the last one:
const firstName = 'Jeniffer';
const result = firstName.match(/^.|.$/gi).reduce((s, c, i) => `${s}${!i ? `${c}****` : c }`, '');
console.log(result);
I have some code which outputs as follows:
function replaceAllButLast(str, splitRegex, pOld, pNew) {
var parts = str.split(splitRegex)
if (parts.length === 1) return str
return parts.slice(0, -1).join(pNew) + pOld + parts.slice(-1)
}
var str = "fred\r\nfred\r\nfred\r\n"
var desiredResult = replaceAllButLast(str, /(?:\r?\n|\r)/, '\n', '\n+')
console.log(desiredResult)
The result is nearly as desired. However, the code assumes that the regex split operation is splitting on \n and thus is replacing it with \n
However, it may actually be splitting on \r\n (windows - as in the example) or \r (old macs)
Does anyone have some code that would give the same output as the code here BUT will preserve the original line break characters whilst still adding the + after a newline (except on the last line).
I am using pure vanilla JavaScript.
PS I must use the regex /(?:\r?\n|\r)/
PPS There is no need to use .split().
This will keep the last newline as it is but others added a +, see replace
var str = "fred\r\nfred\r\nfred\r\n";
var splitRegexp = new RegExp(/(?:\r?\n|\r)/, 'g')
var newstr = str.replace(splitRegexp, function(match, offset, string) {
var follow = string.slice(offset);
var isLast = follow.match(splitRegexp).length == 1;
if (!isLast) {
return match + '+';
} else {
return match;
}
})
console.log(newstr)
I've replaced your regexp with visible chars so you can see what's going on:
var input = "fredEOLfredENDLfredFINfred";
input = input.replace(/(EOL|ENDL|FIN)/g, "$1+");
console.log(input);
I'm solving a puzzle and I have an idea of how to solve this problem, but I would like some guidance and hints.
Suppose I have the following, Given n amount of words to input, and m amount of word combos without spaces, I will have some functionality as the following.
4
this
is
my
dog
5
thisis // outputs 1
thisisacat // 0, since a or cat wasnt in the four words
thisisaduck // 0, no a or cat
thisismy // 1 this,is,my is amoung the four words
thisismydog // 1
My thoughts
First What I was thinking of doing is storing those first words into an array. After that, I check if any of those words is the first word of those 5 words
Example: check if this is in the first word thisis. It is! Great, now remove that this, from thisis to get simply just is, now delete the original string that corresponded to that equality and keep iterating over the left overs (now is,my,dog are available). If we can keep doing this process, until we get an empty string. We return 1, else return 0!
Are my thoughts on the right track? I think this would be a good approach (By the way I would like to implement this in javascript)
Sorting words from long to short may in some cases help to find a solution quicker, but it is not a guarantee. Sentences that contain the longest word might only have a solution if that longest word is not used.
Take for instance this test case:
Words: toolbox, stool, boxer
Sentence: stoolboxer
If "toolbox" is taken as a word in that sentence, then the remaining characters cannot be matched with other valid words. Yet, there is a solution, but only if the word "toolbox" is not used.
Solution with a Regular Expression
When regular expressions are allowed as part of the solution, then it is quite simple. For the above example, the regular expression would be:
^(toolbox|stool|boxer)*$
If a sentence matches that expression, it is a solution. If not, then not. This is quite straightforward, and doesn't really require an algorithm. All is done by the regular expression interpreter. Here is a snippet:
var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg'];
var regex = new RegExp('^(' + words.join('|') + ')*$');
sentences.forEach(sentence => {
// search returns a position. It should be 0:
console.log(sentence + ': ' + (sentence.search(regex) ? 'No' : 'Yes'));
});
But using regular expressions in an algorithm-challenge feels like cheating: you don't really write the algorithm, but rely on the regular expression implementation to do the job for you.
Without Regular Expressions
You could use this algorithm: first check whether a word matches at the start of the input sentence, and if so, remove that first occurrence from it. Then repeat this for the remaining part of the sentence. If this can be repeated until no characters are left over, you have a solution.
If characters are left over which cannot be matched with any word... well, then you cannot really conclude there is no solution for that sentence. It might be that some earlier made word choice was the wrong one, and there was an alternative. So to cope with that, your algorithm could backtrack and try other words.
This principle can be implemented through recursion. To gain memory-efficiency, you could leave the original sentence in-tact, and work with an index in that sentence instead.
The algorithm is implemented in arrow-function testString:
var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg'];
var testString = (words, str, i = 0) =>
i >= str.length || words.some( word =>
str.substr(i, word.length) == word && testString(words, str, i + word.length)
);
sentences.forEach(sentence => {
console.log(sentence + ': ' + (testString(words, sentence) ? 'Yes' : 'No'));
});
Or, the same in non-arrow-function syntax:
var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg'];
var testString = function (words, str, i = 0) {
return i >= str.length || words.some(function (word) {
return str.substr(i, word.length) == word
&& testString(words, str, i + word.length);
});
}
sentences.forEach(function (sentence) {
console.log(sentence + ': ' + (testString(words, sentence) ? 'Yes' : 'No'));
});
... and without some(), forEach() or ternary operator:
var words = ['this','is','a','string'];
var sentences = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg'];
function testString (words, str, i = 0) {
if (i >= str.length) return true;
for (var k = 0; k < words.length; k++) {
var word = words[k];
if (str.substr(i, word.length) == word
&& testString(words, str, i + word.length)) {
return true;
}
}
}
for (var n = 0; n < sentences.length; n++) {
var sentence = sentences[n];
if (testString(words, sentence)) {
console.log(sentence + ': Yes');
} else {
console.log(sentence + ': No');
}
}
Take the 4 words, put them into a regex.
Use that regex to split each string.
Take the length of the resulting array (subtract one for the initial length of one).
var size = 'thisis'.split(/this|is|my|dog/).length - 1
Or if your list of words is an array
var search = new RegExp(words.join('|'))
var size = 'thisis'.split(search).length - 1
Either way you are splitting up the string by the list of words you have defined.
You can sort the words by length to ensure that larger words are matched first by
words.sort(function (a, b) { return b.length - a.length })
Here is the solution for anyone interested
var input = ['this','is','a','string']; // This will work for any input, but this is a test case
var orderedInput = input.sort(function(a,b){
return b.length - a.length;
});
var inputRegex = new RegExp(orderedInput.join('|'));
// our combonation of words can be any size in an array, just doin this since prompt in js is spammy
var testStrings = ['thisis','thisisastring','thisisaduck','thisisastringg','stringg'];
var foundCombos = (regex,str) => !str.split(regex).filter(str => str.length).length;
var finalResult = testStrings.reduce((all,str)=>{
all[str] = foundCombos(inputRegex,str);
if (all[str] === true){
all[str] = 1;
}
else{
all[str] = 0;
}
return all;
},{});
console.log(finalResult);
I am learning regex, and I got a doubt. Let's consider
var s = "YYYN[1-20]N[]NYY";
Now, I want to replace/insert the '1-8' between [ and ] at its second occurrence.
Then output should be
YYYN[1-20]N[1-8]NYY
For that I had tried using replace and passing a function through it as shown below:
var nth = 0;
s = s.replace(/\[([^)]+)\]/g, function(match, i, original) {
nth++;
return (nth === 1) ? "1-8" : match;
});
alert(s); // But It wont work
I think that regex is not matchIing the string that I am using.
How can I fix it?
You regex \[([^)]+)\] will not match empty square brackets since + requires at least 1 character other than ). I guess you wanted to write \[[^\]]*\].
Here is a fix for your solution:
var s = "YYYN[1-20]N[]NYY";
var nth = 0;
s = s.replace(/\[[^\]]*\]/g, function (match, i, original) {
nth++;
return (nth !== 1) ? "[1-8]" : match;
});
alert(s);
Here is another way of doing it:
var s = "YYYN[1-20]N[]NYY";
var nth = 0;
s = s.replace(/(.*)\[\]/, "$1[1-8]");
alert(s);
The regex (.*)\[\] matches and captures into Group 1 greedily as much text as possible (thus we get the last set of empty []), and then matches empty square brackets. Then we restore the text before [] with $1 backreference and add out string 1-8.
If it’s only two occurences of square brackets, then this will work:
/(.*\[.*?\].*\[).*?(\].*)/
This RegEx has “YYYN[1-20]N[” as the first capturing group and “]NYY” as the second.
I suggest using simple split and join operations:
var s = "YYYN[1-20]N[]NYY";
var arr = s.split(/\[/)
arr[2] = '1-8' + arr[2]
var r = arr.join('[')
//=> YYYN[1-20]N[1-8]NYY
You can use following regex :
var s = "YYYN[1-20]N[]NYY";
var nth = 0;
s = s.replace(/([^[]+\[(?:[^[]+)\][^[]+)\[[^[]+\](.+)/, "$1[1-8]$2");
alert(s);
The first part ([^[]+\[([^[]+)\][^[]+) will match a string contain first sub-string between []. and \[[^[]+\] would be the second one which you want and the last part (.+?) match the rest of your string.
I nee to replace all numbers after underline inside a string.
I think that I can use Regex, but I don't know how to use Regex Syntax
See an example of my string:
milton_0
milton_1
If that is the standard format, You can use split()
var str = 'milton_1';
alert(str.split('_')[1]);
You don't need regex for this. The following code in enough
var str = "milton_0";
str = str.substring(0,str.indexOf("_"));
I'm not sure how specific or broad you want to be, but you can try this:
var starter = "milton_1";
var specialVal = "asdf";
var re = /^(milton_)(\d+)$/;
var replaced = starter.replace(re, function (match, p1) {
return p1 + specialVal;
});
console.log(replaced);
http://jsfiddle.net/ne4cD/
This will match a string starting with "milton_" and ending with digits. It replaces any digits after the "_" with the specialVal value.
An example of simply incrementing that number is:
var starter = "milton_1";
var re = /^(milton_)(\d+)$/;
var replaced = starter.replace(re, function (match, p1, p2) {
return p1 + (+p2 + 1);
});
console.log(replaced);
http://jsfiddle.net/ne4cD/2/
UPDATE:
If the "milton" part isn't static, then you're really only targeting the "_" with digits after it. So something like this:
var starter = "asdfkjlasdfjksadf_1";
var specialVal = "asdf";
var re = /(_)(\d+)/g;
var replaced = starter.replace(re, function (match, p1) {
return p1 + specialVal;
});
console.log(replaced);
http://jsfiddle.net/ne4cD/3/
And maybe a little better to see: http://jsfiddle.net/ne4cD/4/
First of all you need them as list for handling easily.
var listOfStrings = yourStringObject('whateverYourCharacterUnderEachWord').ToList<string>();
After that you need to get rid of number for each string in the list and add what you want.
foreach(string word in listOfStrings){
word = word.Substring(0,word.IndexOf('_')+1);
word = word + "characterThatYouWantToAddHere"
}