Below re-joins an array of words after splitting it with /\s+/. But it only joins it with space, replacing the original separator caught in between. I want to return the original separator caught between words, like line-breaks which are also matched on the RegExp expression.
/** wraps URLS found in message with `<span class="hyperlink"></span>`. */
parseURLs(message) {
if (!message) return '';
return message
.split(/\s+/)
.map(word => {
console.log('test word:', word);
try {
const url = new URL(word);
return `<span class="hyperlink">${word}</span>`;
} catch {
return word;
}
})
.join(' ');
}
Since each word will have its own separator (as an arbitrary number of whitespaces) you can't rely on join to serialize the array of words.
But if you change your parsing strategy so that instead of using split you go straight with regular expressions, you can match your words followed by zero or * amount of whitespaces.
const matches = message.matchAll(/(\S+)(\s*)/g);
Then you can just loop the matches found and build your own array of objects like I did here as {fullmatch, word, separator}.
In the end you can process this array as you best prefer and in the end serialize it back to string using for example reduce
*Here I also added your transform logic that will process the parsed word in .processed so that it will be used during the serialization process but yet you will have all the parsed bits conserved in a structured way.
const o = parseURLs('test3spaces test1space testnospace https://www.google.com');
console.log(o);
function parseURLs(message) {
if (!message) return '';
//regex to match nonspace characters followed by spaces
const matches = message.matchAll(/(\S+)(\s*)/g);
//pushes all matches in words (as objects {fullmatch, word, separator})
const words = [...matches].map( match => {
const [fullmatch, word, separator] = match;
const parsed = {fullmatch, word, separator};
//**--[This is the trasform of the word as copied from your snippet]--**
try {
const url = new URL(word);
parsed.processed = `<span class="hyperlink">${word}</span>`;
} catch {
parsed.processed = word;
}
//**--
return parsed;
});
//returns the serialization of words array
return words.reduce( (serialized, word) => serialized += `${word.processed}${word.separator}`, '');
}
You've thrown away the whitespace when splitting, you don't get that back.
function parseURLs(message) {
return message && message.replace(/\S+/g, word => {
console.log('test word:', word);
try {
const url = new URL(word);
return `<span class="hyperlink">${word}</span>`;
} catch (err) {
return word;
}
});
}
Related
for self development purposes I want to create a function with two parameters - string and an array. It should return a string without the letters given in the array.
function filterLetters(str, lettersToRemove) {
}
const str = filterLetters('Achievement unlocked', ['a', 'e']);
Could someone give me any pointers on how to achieve this?
For each letter to be replaced, remove it (i.e. replace it with ''). When done, return the updated string:
function filterLetters(str, lettersToRemove) {
lettersToRemove.forEach(function(letter){
str = str.replaceAll(letter, '');
})
return str
}
Also see How to replace all occurrences of a string in JavaScript.
You can use regex with replaceAll to remove all char from the string.
If you want to consider upper case also then use 'gi' else no need for regex also. str.replaceAll(char, '')
const removeChar = (str, c) => str.replaceAll(new RegExp(`[${c}]`, "gi"), "");
const run = () => {
const str = "Achievement unlocked";
const chars = ["a", "e"];
let result = str;
chars.forEach((char) => {
result = removeChar(result, char);
});
return result;
};
console.log(run());
One easy way to do this would be to just loop over each value in the array and call the replace string method on str with each indices character. The code below does this.
function filterLetters(str, lettersToRemove){
for (const letter of lettersToRemove){
str = str.replaceAll(letter,"");
}
return str;
}
You should just transform the string into array by using split function and loop over that array and check if each character exist in the second argument of your function. To make this function not case sensitive I use toLowerCase to convert character to
function filterLetters(str, lettersToRemove) {
return str.split('').reduce((acc, current)=> {
if(lettersToRemove.indexOf(current.toLowerCase()) == -1){
acc.push(current);
}
return acc;
}, []).join('');
}
const str = filterLetters('Achievement unlocked', ['a', 'e']);
console.log(str);
Create a regular expression by joining the array elements with a | (so a|e), and then use replaceAll to match those letters and replace them with an empty string.
If you want both upper- and lower-case letters removed add the "case-insenstive" flag to the regex. 'gi' rather than 'g'.
function filterLetters(str, lettersToRemove) {
const re = new RegExp(lettersToRemove.join('|'), 'g');
return str.replaceAll(re, '');
}
const str = filterLetters('Achievement unlocked', ['a', 'e']);
console.log(str);
I have made a simple select component in Vue with a search/filter system. Based on the user input I'm showing some Belgium city suggestions.
Working example: https://codesandbox.io/s/wandering-lake-lecok?file=/src/components/Select.vue (Sometimes there is an error message in Codesandbox. Refresh the build in browser and it should work)
I want to take the UX one step further and show the matching part of the user input bold and underlined. Therefore I have a working makeBold function. By splitting the suggestion string into multiple parts I can add a bold and underline tag and return the suggestion.
computed: {
results() {
return this.options.filter((option) =>
option.display_name
.replaceAll("-'", "")
.toLowerCase()
.includes(this.searchInput.replaceAll("-'", "").toLowerCase())
);
},
},
methods: {
makeBold(str, query) {
const n = str.toUpperCase();
const q = query.toUpperCase();
const x = n.indexOf(q);
if (!q || x === -1) {
return str;
}
const l = q.length;
return (
str.substr(0, x) + "<b><u>" + str.substr(x, l) + "</u></b>" + str.substr(x + l)
);
},
}
One problem, a lot of cities in Belgium use dashes and/or apostrophes. In the suggestions function I'm removing this characters so a user doesn't need to type them. But in the makeBold function I would like to make this characters bold and underlined.
For example:
When the input is 'sint j', 'sintj' or 'Sint-j' I want the suggestions to look like 'Sint-Jans-Molenbeek' and 'Sint-Job in't Goor'
Is there someone who can give me a breakdown on how to achieve this?
I would propose using a mask, to save the city name structure, and after you find the start and end index of substring in city name, restore the original string from mask, inserting the appropriate tags at the start and end index using a replacer function. this way you would not worry about any other non-word characters or other unexpected user input.
Here is the makeBold function:
makeBold(str, query) {
// mask all word characters in city name
const city_mask = str.replace(/\w/g, "#");
// strip city and query string from any non-word character
let query_stripped = query.toLowerCase().replace(/\W/g, "");
let string_stripped = str.replace(/\W/g, "");
// find the index of querystring in city name
let index = string_stripped.toLowerCase().indexOf(query_stripped);
if (index > -1 && query_stripped.length) {
// find the end position of substring in stripped city name
let end_index = index + query_stripped.length - 1;
// replacer function for each masked character.
// it will add to the start and end character of substring the corresponding tags,
// replacing all masked characters with the original one.
function replacer(i) {
let repl = string_stripped[i];
if (i === index) {
repl = "<b><u>" + repl;
}
if (i === end_index) {
repl = repl + "</u></b>";
}
return repl;
}
let i = -1;
// restore masked string
return city_mask.replace(/#/g, (_) => {
i++;
return replacer(i);
});
}
return str;
}
And here is the working sandbox. I've changed a bit your computed results to strip all non-word characters.
One way is to transform your search string into a RegExp object and use replace(regexp, replacerFunction) overload of string to achieve this.
For example the search string is "sintg"
new RegExp(this.searchInput.split("").join("-?"), "i");
Turns it into /s-?i-?n-?t-?g/gi
-? indicates optional - character and
"i" at the end is the RegExp case insensitive flag
Applied to codesandbox code you get this
computed: {
results() {
const regex = new RegExp(this.searchInput.split("").join("-?"), "i");
return this.options.filter((option) => option.display_name.match(regex));
},
},
methods: {
makeBold(str, query) {
const regex = new RegExp(query.split("").join("-?"), "i");
return str.replace(regex, (match) => "<b><u>" + match + "</u></b>");
},
},
Which gives this result
However there is a caveat: There will be errors thrown if the user puts a RegExp special symbol in the search box
To avoid this the initial search input text needs to get RegExp escape applied.
Such as:
new RegExp(escapeRegExp(this.searchInput).split("").join("-?"), "i");
But there is no native escapeRegExp method.
You can find one in Escape string for use in Javascript regex
There is also an escapeRegExp function in lodash library if it's already in your list of dependencies (saves you from adding another function)
You could create a function that removes all spaces and - in the query and city string. If the city includes the query, split the query string on the last letter and get the occurences of that letter in the query. Calculate the length to slice and return the matching part of the original city string.
const findMatch = (q, c) => {
const query = q.toLowerCase().replace(/[\s-]/g, "");
const city = c.toLowerCase().replace(/[\s-]/g, "");
if (city.includes(query)) {
const last = query.charAt(query.length - 1); // last letter
const occ = query.split(last).length - 1; // get occurences
// calculate slice length
const len = c.toLowerCase().split(last, occ).join(" ").length + 1;
return c.slice(0, len);
}
return "No matching city found."
}
const city = "Sint-Jan Test";
console.log(findMatch("sint j", city));
console.log(findMatch("sintj", city));
console.log(findMatch("Sint Jan t", city));
console.log(findMatch("sint-j", city));
console.log(findMatch("Sint-J", city));
console.log(findMatch("SintJan te", city));
I am trying to search in a string and trying to extract a particular thing from the string.
here are the example i am trying to solve.
const string = 'xtyzjdjgdjf +91888123455, +918885558565 +916885123456, +911234569870'
i am trying to extract only '+91888123455, +918885558565 +916885123456, +911234569870'
but the number is dynamic and it changes as per the response
about the pattern of the used regex ... /\+\d+,{0,1}/g ...
\+ ... match a single mandatory + sign ... followed by ...
\d+ ... at least one digit (or a sequence of digits) ... followed by ...
,{0,1} ... a single but optional comma.
g ... search/match the pattern globally.
function extractValidNumberSequences(str) {
return str.match(/\+\d+,{0,1}/g).join(' ');
}
const test = `
xtyzjdjgdjf +91888123455, +918885558565 +916885123456,,, +91123456987 dsjk jjd
sag sadgsadj 43865984 dsjghj, +918885558565 +916885123456,,, +91123456987 dsjk
`;
console.log(`extractValidNumberSequences(test) : "${ extractValidNumberSequences(test) }"`);
.as-console-wrapper { min-height: 100%!important; top: 0; }
The easiest way is using Regex: /\+\d*/g.
This Regex is searching for all the strings that starts with + and have 0 or more numbers after that.
const string = 'xtyzjdjgdjf +91888123455, +918885558565 +916885123456, +911234569870';
const result = [...string.matchAll(/\+\d*/g)] // Get all the regex matches
.map(([text]) => text) // Grabbing the first element in the array which is the text
.join(','); // Join the text together
console.log(result);
Resources
String#matchAll
regexr - A great tool to visualise and understand Regex expressions
var stringVal = "'xtyzjdjgdjf +91888123455, +918885558565 +916885123456, +911234569870".replace('xtyzjdjgdjf','');
console.log(stringVal); //prints: +91888123455, +918885558565 +916885123456, +911234569870
For all occurrences to be discarded use:
Eg --
var ret = "data-123".replace(/data-/g,'');
PS: The replace function returns a new string and leaves the original string unchanged, so use the function return value after the replace() call.
Okay, let me get this straight: You're looking to extract a sequence of numbers from a string beginning in a "+" symbol and ending in a "," character?
The way you could do that is looping through the string.
let Raw = "udhaiuedh +34242, +132354"
function ExtractNumbers(ToDecode) {
let StartSet = ["+"]
let EndSet = [","," "]
let Cache = ""
let Finished = []
for (Char of ToDecode) {
if (StartSet.includes(Char)) {
if (Cache.length != 0) {
Finished.push(Cache)
}
Cache = ""
} else if (EndSet.includes(Char)) {
if (Cache.length != 0) {
Finished.push(Cache)
}
Cache = ""
} else {
if (Number(Char)) {
Cache = Cache + String(Char)
}
}
}
if (Cache.length != 0) {
Finished.push(Cache)
}
return Finished
}
console.log(ExtractNumbers(Raw))
It's not perfect, but a nice example to get you started :)
const string = 'xtyzjdjgdjf +91888123455, +918885558565 +916885123456, +911234569870'
const extractMe = '+91888123455, +918885558565 +916885123456, +911234569870'
if (string.includes(extractMe)) {
// extractMe is what you want to extract
}
I'm learning how to capitalize the first letter of each word in a string and for this solution I understand everything except the word.substr(1) portion. I see that it's adding the broken string but how does the (1) work?
function toUpper(str) {
return str
.toLowerCase()
.split(' ')
.map(function(word) {
return word[0].toUpperCase() + word.substr(1);
})
.join(' ');
}
console.log(toUpper("hello friend"))
The return value contain 2 parts:
return word[0].toUpperCase() + word.substr(1);
1) word[0].toUpperCase(): It's the first capital letter
2) word.substr(1) the whole remain word except the first letter which has been capitalized. This is document for how substr works.
Refer below result if you want to debug:
function toUpper(str) {
return str
.toLowerCase()
.split(' ')
.map(function(word) {
console.log("First capital letter: "+word[0]);
console.log("remain letters: "+ word.substr(1));
return word[0].toUpperCase() + word.substr(1);
})
.join(' ');
}
console.log(toUpper("hello friend"))
Or you could save a lot of time and use Lodash
Look at
https://lodash.com/docs/4.17.4#startCase -added/edited-
https://lodash.com/docs/4.17.4#capitalize
Ex.
-added/edited-
You may what to use startCase, another function for capitalizing first letter of each word.
_.startCase('foo bar');
// => 'Foo Bar'
and capitalize for only the first letter on the sentence
_.capitalize('FRED');
// => 'Fred'
Lodash is a beautiful js library made to save you a lot of time.
There you will find a lot of time saver functions for strings, numbers, arrays, collections, etc.
Also you can use it on client or server (nodejs) side, use bower or node, cdn or include it manually.
Here is a quick code snippet. This code snippet will allow you to capitalize the first letter of a string using JavaScript.
function capitlizeText(word)
{
return word.charAt(0).toUpperCase() + word.slice(1);
}
The regexp /\b\w/ matches a word boundary followed by a word character. You can use this with the replace() string method to match then replace such characters (without the g (global) regexp flag only the first matching char is replaced):
> 'hello my name is ...'.replace(/\b\w/, (c) => c.toUpperCase());
'Hello my name is ...'
> 'hello my name is ...'.replace(/\b\w/g, (c) => c.toUpperCase());
'Hello My Name Is ...'
function titleCase(str) {
return str.toLowerCase().split(' ').map(x=>x[0].toUpperCase()+x.slice(1)).join(' ');
}
titleCase("I'm a little tea pot");
titleCase("sHoRt AnD sToUt");
The major part of the answers explains to you how works the substr(1). I give to you a better aproach to resolve your problem
function capitalizeFirstLetters(str){
return str.toLowerCase().replace(/^\w|\s\w/g, function (letter) {
return letter.toUpperCase();
})
}
Explanation:
- First convert the entire string to lower case
- Second check the first letter of the entire string and check the first letter that have a space character before and replaces it applying .toUpperCase() method.
Check this example:
function capitalizeFirstLetters(str){
return str.toLowerCase().replace(/^\w|\s\w/g, function (letter) {
return letter.toUpperCase();
})
}
console.log(capitalizeFirstLetters("a lOt of words separated even much spaces "))
Consider an arrow function with an implicit return:
word => `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}`
This will do it in one line.
Using ES6
let captalizeWord = text => text.toLowerCase().split(' ').map( (i, j) => i.charAt(0).toUpperCase()+i.slice(1)).join(' ')
captalizeWord('cool and cool')
substr is a function that returns (from the linked MDN) a new string containing the extracted section of the given string (starting from the second character in your function). There is a comment on the polyfill implementation as well, which adds Get the substring of a string.
function titlecase(str){
let titlecasesentence = str.split(' ');
titlecasesentence = titlecasesentence.map((word)=>{
const firstletter = word.charAt(0).toUpperCase();
word = firstletter.concat(word.slice(1,word.length));
return word;
});
titlecasesentence = titlecasesentence.join(' ');
return titlecasesentence;
}
titlecase('this is how to capitalize the first letter of a word');
const capitalize = str => {
if (typeof str !== 'string') {
throw new Error('Invalid input: input must of type "string"');
}
return str
.trim()
.replace(/ {1,}/g, ' ')
.toLowerCase()
.split(' ')
.map(word => word[0].toUpperCase() + word.slice(1))
.join(' ');
};
sanitize the input string with trim() to remove whitespace from the leading and trailing ends
replace any extra spaces in the middle with a RegExp
normalize and convert it all toLowerCase() letters
convert the string to an array split on spaces
map that array into an array of capitalized words
join(' ') the array with spaces and return the newly capitalized string
Whole sentence will be capitalize only by one line
"my name is John".split(/ /g).map(val => val[0].toUpperCase() + val.slice(1)).join(' ')
Output "My Name Is John"
A nice simple solution, using pure JavaScript. JSFiddle
function initCap(s) {
var result = '';
if ((typeof (s) === 'undefined') || (s == null)) {
return result;
}
s = s.toLowerCase();
var words = s.split(' ');
for (var i = 0; i < words.length; ++i) {
result += (i > 0 ? ' ' : '') +
words[i].substring(0, 1).toUpperCase() +
words[i].substring(1);
}
return result;
}
Here is an example of how substr works: When you pass in a number, it takes a portion of the string based on the index you provided:
console.log('Testing string'.substr(0)); // Nothing different
console.log('Testing string'.substr(1)); // Starts from index 1 (position 2)
console.log('Testing string'.substr(2));
So, they are taking the first letter of each word, capitalizing it, and then adding on the remaining of the word. Ance since you are only capitalizing the first letter, the index to start from is always 1.
In word.substr(i), the param means the index of the word. This method cuts the word from the letter whose index equals i to the end of the word.
You can also add another param like word.substr(i, len), where len means the length of the character segmentation. For example:
'abcde'.substr(1, 2) → bc.
function toTitleCase(str)
{
return str.replace(/\w\S*/g, function(txt){return
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
Just map through if an array set the first letter as uppercase and concatenate with other letters from index 1.
The array isn't your case here.
const capitalizeNames = (arr) => {
arr.map((name) => {
let upper = name[0].toUpperCase() + name.substr(1)
console.log(upper)
})
}
Here's another clean way of Capitalizing sentences/names/... :
const capitalizeNames =(name)=>{
const names = name.split(' ') // ['kouhadi','aboubakr',essaaddik']
const newCapName = [] // declaring an empty array
for (const n of names){
newCapName.push(n.replace(n[0], n[0].toUpperCase()));
}
return newCapName.join(' ')
}
capitalizeNames('kouhadi aboubakr essaaddik'); // 'Kouhadi Aboubakr Essaaddik'
You could use these lines of code:
function toUpper(str) {
return [str.split('')[0].toUpperCase(), str.split('').slice(1, str.split('').length).join("")].join("")
}
Basically it will split all characters, slice it, create a new array without the first entry/character and replace the first entry/character with an uppercase verion of the character.
(Yes, this was tested and it works on Edge, Chrome and newer versions of Internet Explorer.)
This is probably not the greatest answer, but hopefully it works well enough for you.
I am still rather new to JavaScript and I am having an issue of getting the first character of the string inside the array to become uppercase.
I have gotten to a point where I have gotten all the texted lowercase, reversed the text character by character, and made it into a string. I need to get the first letter in the string to uppercase now.
function yay () {
var input = "Party like its 2015";
return input.toLowerCase().split("").reverse().join("").split(" ");
for(var i = 1 ; i < input.length ; i++){
input[i] = input[i].charAt(0).toUpperCase() + input[i].substr(1);
}
}
console.log(yay());
I need the output to be "partY likE itS 2015"
Frustrating that you posted your initial question without disclosing the desired result. Lots of turmoil because of that. Now, that the desired result is finally clear - here's an answer.
You can lowercase the whole thing, then split into words, rebuild each word in the array by uppercasing the last character in the word, then rejoin the array:
function endCaseWords(input) {
return input.toLowerCase().split(" ").map(function(item) {
return item.slice(0, -1) + item.slice(-1).toUpperCase();
}).join(" ");
}
document.write(endCaseWords("Party like its 2015"));
Here's a step by step explanation:
Lowercase the whole string
Use .split(" ") to split into an array of words
Use .map() to iterate the array
For each word, create a new word that is the first part of the word added to an uppercased version of the last character in the word
.join(" ") back together into a single string
Return the result
You could also use a regex replace with a custom callback:
function endCaseWords(input) {
return input.toLowerCase().replace(/.\b/g, function(match) {
return match.toUpperCase();
});
}
document.write(endCaseWords("Party like its 2015"));
FYI, there are lots of things wrong with your original code. The biggest mistake is that as soon as you return in a function, no other code in that function is executed so your for loop was never executed.
Then, there's really no reason to need to reverse() the characters because once you split into words, you can just access the last character in each word.
Instead of returning the result splitting and reversing the string, you need to assign it to input. Otherwise, you return from the function before doing the loop that capitalizes the words.
Then after the for loop you should return the joined string.
Also, since you've reverse the string before you capitalize, you should be capitalizing the last letter of each word. Then you need to reverse the array before re-joining it, to get the words back in the original order.
function yay () {
var input = "Party like its 2015";
input = input.toLowerCase().split("").reverse().join("").split(" ");
for(var i = 1 ; i < input.length ; i++){
var len = input[i].length-1;
input[i] = input[i].substring(0, len) + input[i].substr(len).toUpperCase();
}
return input.reverse().join(" ");
}
alert(yay());
You can use regular expression for that:
input.toLowerCase().replace(/[a-z]\b/g, function (c) { return c.toUpperCase() });
Or, if you can use arrow functions, simply:
input.toLowerCase().replace(/[a-z]\b/g, c => c.toUpperCase())
Here's what I would do:
Split the sentence on the space character
Transform the resulting array using .map to capitalize the first character and lowercase the remaining ones
Join the array on a space again to get a string
function yay () {
var input = "Party like its 2015";
return input.split(" ").map(function(item) {
return item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
}).join(" ");
}
console.log(yay());
Some ugly, but working code:
var text = "Party like its 2015";
//partY likE itS 2015
function yay(input) {
input = input.split(' ');
arr = [];
for (i = 0; i < input.length; i++) {
new_inp = input[i].charAt(0).toLowerCase() + input[i].substring(1, input[i].length - 1) + input[i].charAt(input[i].length - 1).toUpperCase();
arr.push(new_inp);
}
str = arr.join(' ');
return str;
}
console.log(yay(text));
Try using ucwords from PHP.js. It's quite simple, actually.
String.prototype.ucwords = function() {
return (this + '')
.replace(/^([a-z\u00E0-\u00FC])|\s+([a-z\u00E0-\u00FC])/g, function($1) {
return $1.toUpperCase();
});
}
var input = "Party like its 2015";
input = input.charAt(0).toLowerCase() + input.substr(1);
input = input.split('').reverse().join('').ucwords();
input = input.split('').reverse().join('');
Note: I modified their function to be a String function so method chaining would work.
function yay(str)
{
let arr = str.split(' ');
let farr = arr.map((item) =>{
let x = item.split('');
let len = x.length-1
x[len] = x[len].toUpperCase();
x= x.join('')
return x;
})
return farr.join(' ')
}
var str = "Party like its 2015";
let output = yay(str);
console.log(output) /// "PartY likE itS 2015"
You can split and then map over the array perform uppercase logic and retun by joining string.
let string = "Party like its 2015";
const yay = (string) => {
let lastCharUpperCase = string.split(" ").map((elem) => {
elem = elem.toLowerCase();
return elem.replace(elem[elem.length - 1], elem[elem.length - 1].toUpperCase())
})
return lastCharUpperCase.join(" ");
}
console.log(yay(string))