How to remove extra occurrences of a letter in a string? [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Using Javascript is there a way to remove extra occurrences of a specific letter in a string?
For example:
remove_extra('a', 'caaaat')
//=> 'cat'
I know there must be a brute force way to do something like this but is there an elegant way? I'm not sure how to approach this algorithm.

you can do this with regex:
var test = "aaabbbccc";
console.log(test.replace(/(.)(?=.*\1)/g, "")); //would print abc
var test2 = "caaaaat";
console.log(test2.replace(/(.)(?=.*\1)/g, "")); //would print cat

Sorry, I misunderstood your question.
To only keep one instance of specified char:
function onlyOneCharOf(string, pattern) {
let first = true;
//if (pattern.length !==1) throw Error("Expected one character");
pattern=pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); //escape RegEx special chars
return string.replace(new RegExp(pattern, "g"), value => {
if (first) {
first = false;
return value;
}
return "";
});
}
console.log(onlyOneCharOf("zzzzzaaabbbbcccc", "a"));
Note: the pattern given to the function is used to create a RegEx. Since some characters are special characters, those characters must be escaped. I updated the function to do that for you. You might also want to check the length, but the length might be larger than 1 for some unicode code points.
If you only want any character to appear once, you can use a Set:
function unique(string) {
return Array.from(new Set(string.split(''))).join('');
}
console.log(unique("caaaat"));
A value in a Set may only occur once.

You can use Array.from to explode a string:
Array.from('caaaat');
//=> ["c", "a", "a", "a", "a", "t"]
You can then use Array#filter to keep everything that is neither "a" nor the first occurrence of "a":
Array.from('caaaat').filter((x, i, xs) => x !== 'a' || xs.indexOf(x) === i).join('');
//=> "cat"
(I leave it to you as an exercise to put this into a reusable function.)
Just be aware that if you choose to interpret char as a regular expression without validating it first, you may have unexpected results:
function onlyOneCharOf(string, char) {
let first = true;
return string.replace(new RegExp(char, "g"), value => {
if (first) {
first = false;
return value;
}
return "";
});
}
onlyOneCharOf('caaat', '.');
//=> "c"
onlyOneCharOf('caaat', '?');
//=> SyntaxError

Related

split method to return only values split by a comma not quotes in comma [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 days ago.
Improve this question
I want to split the string below by a default comma which is , and ignore the "," part.
Has anyone come up with a solution for this? Tried a bunch of solutions, but doesn't work.
My string: (testing","a framework), hello world, testing","antother_framework
expected result:
["testing","a framework", "hello world", "testing","antother_framework]
not the nicest way, with regex you could grouped the replace but it works
const str = '(testing","a framework), hello world, testing","antother_framework';
let arr = str.split(',');
console.log(arr);
for (let i = 0; i < arr.length; i++) {
arr[i] = arr[i].replaceAll('(', '');
arr[i] = arr[i].replaceAll(')', '');
arr[i] = arr[i].replaceAll('\"', '');
arr[i] = arr[i].trim();
}
console.log(arr);
You could use this function:
function splitByCommas(str) {
return str.split(/,(?=(?:[^"]*"[^"]*")*[^"]*$)/);
}
Explanation:
/,(?=(?:[^"]"[^"]")[^"]$)/ -> match the comma outside of the quotes
(?:[^"]"[^"]")* -> match the quotes and the text inside the quotes
[^"]*$ -> match the remaining text after the last quote
If you run the function like this:
console.log(splitByCommas('(testing","a framework), hello world, testing","antother_framework'));
It will give the following output:
[
'(testing","a framework)',
' hello world',
' testing","antother_framework'
]
If you want to also trim the whitespaces, you can use this:
function splitByCommas(str) {
return str.split(/,(?=(?:[^"]*"[^"]*")*[^"]*$)/).map(function (item) {
return item.trim();
}
);
}
For the same input giving you:
[
'(testing","a framework)',
'hello world',
'testing","antother_framework'
]

Ho do I split these 2 string using Regex? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Following are 2 strings:
" at callback (/Users/lem/Projects/RingAPI/packages/server/node_modules/loopback-connector-rest/lib/rest-builder.js:541:21)"
" at /Users/lem/Projects/RingAPI/packages/server/node_modules/#loopback/repository/node_modules/loopback-datasource-juggler/lib/observer.js:269:22"
How do I split them to these using JS and Regex?
['callback', '/Users/lem/Projects/RingAPI/packages/server/node_modules/loopback-connector-rest/lib/rest-builder.js', '541', '21']
['', '/Users/lem/Projects/RingAPI/packages/server/node_modules/#loopback/repository/node_modules/loopback-datasource-juggler/lib/observer.js', '269', '22']
try regexp named groups
https://github.com/tc39/proposal-regexp-named-groups
it adds result readability for such strange regexes ;)
const strings = [
" at callback (/Users/lem/Projects/RingAPI/packages/server/node_modules/loopback-connector-rest/lib/rest-builder.js:541:21)",
" at /Users/lem/Projects/RingAPI/packages/server/node_modules/#loopback/repository/node_modules/loopback-datasource-juggler/lib/observer.js:269:22"
];
const regex = /^\s*?at\s?(?<source>.*?)\s\(?(?<path>.*?):(?<row>\d*):(?<column>\d*)/;
strings.forEach(string => {
const result = string.match(regex);
resultElement.innerHTML +=
'\n' + JSON.stringify({string, "result.groups": result.groups}, null, 4)
})
<pre id="resultElement"/>
You can use regex for such purpose, i.e:
const regex = /at( (?:[a-z]+)?)\(?(.+)\:(\d+)\:(\d+)\)?/;
//const str = " at callback (/Users/lem/Projects/RingAPI/packages/server/node_modules/loopback-connector-rest/lib/rest-builder.js:541:21)";
const str = " at /Users/lem/Projects/RingAPI/packages/server/node_modules/#loopback/repository/node_modules/loopback-datasource-juggler/lib/observer.js:269:22";
const found = str.match(regex);
found.splice(0, 1)
console.log(found)
It works for both strings!
I've wrote simple parse function for you:
function parse(string) {
const functionName = string.match(/at .* /);
return [
...(functionName && [functionName[0].slice(2).trim()] || ['']),
...string.match(/\/.*/)[0].split(':')
];
}
First of all I try to extract function name. If it exists I remove 'at' word and use trim function to remove unnecessary spaces. Then I look for substring beginning with slash '/' and match every character after it. Last step is to split returned string.
I believe it matches your requirements.
I've also prepared demo in stackblitz: https://stackblitz.com/edit/js-ol22yf

How to check if a string contains a WORD in javascript? [duplicate]

This question already has answers here:
How to check if a string contain specific words?
(11 answers)
Closed 3 years ago.
So, you can easily check if a string contains a particular substring using the .includes() method.
I'm interested in finding if a string contains a word.
For example, if I apply a search for "on" for the string, "phones are good", it should return false. And, it should return true for "keep it on the table".
You first need to convert it into array using split() and then use includes()
string.split(" ").includes("on")
Just need to pass whitespace " " to split() to get all words
This is called a regex - regular expression
You can use of 101regex website when you need to work around them (it helps). Words with custom separators aswell.
function checkWord(word, str) {
const allowedSeparator = '\\\s,;"\'|';
const regex = new RegExp(
`(^.*[${allowedSeparator}]${word}$)|(^${word}[${allowedSeparator}].*)|(^${word}$)|(^.*[${allowedSeparator}]${word}[${allowedSeparator}].*$)`,
// Case insensitive
'i',
);
return regex.test(str);
}
[
'phones are good',
'keep it on the table',
'on',
'keep iton the table',
'keep it on',
'on the table',
'the,table,is,on,the,desk',
'the,table,is,on|the,desk',
'the,table,is|the,desk',
].forEach((x) => {
console.log(`Check: ${x} : ${checkWord('on', x)}`);
});
Explaination :
I am creating here multiple capturing groups for each possibily :
(^.*\son$) on is the last word
(^on\s.*) on is the first word
(^on$) on is the only word
(^.*\son\s.*$) on is an in-between word
\s means a space or a new line
const regex = /(^.*\son$)|(^on\s.*)|(^on$)|(^.*\son\s.*$)/i;
console.log(regex.test('phones are good'));
console.log(regex.test('keep it on the table'));
console.log(regex.test('on'));
console.log(regex.test('keep iton the table'));
console.log(regex.test('keep it on'));
console.log(regex.test('on the table'));
You can .split() your string by spaces (\s+) into an array, and then use .includes() to check if the array of strings has your word within it:
const hasWord = (str, word) =>
str.split(/\s+/).includes(word);
console.log(hasWord("phones are good", "on"));
console.log(hasWord("keep it on the table", "on"));
If you are worried about punctuation, you can remove it first using .replace() (as shown in this answer) and then split():
const hasWord = (str, word) =>
str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g,"").split(/\s+/).includes(word);
console.log(hasWord("phones are good son!", "on"));
console.log(hasWord("keep it on, the table", "on"));
You can split and then try to find:
const str = 'keep it on the table';
const res = str.split(/[\s,\?\,\.!]+/).some(f=> f === 'on');
console.log(res);
In addition, some method is very efficient as it will return true if any predicate is true.
You can use .includes() and check for the word. To make sure it is a word and not part of another word, verify that the place you found it in is followed by a space, comma, period, etc and also has one of those before it.
A simple version could just be splitting on the whitespace and looking through the resulting array for the word:
"phones are good".split(" ").find(word => word === "on") // undefined
"keep it on the table".split(" ").find(word => word === "on") // "on"
This just splits by whitespace though, when you need parse text (depending on your input) you'll encounter more word delimiters than whitespace. In that case you could use a regex to account for these characters.
Something like:
"Phones are good, aren't they? They are. Yes!".split(/[\s,\?\,\.!]+/)
I would go with the following assumptions:
Words the start of a sentence always have a trailing space.
Words at the end of a sentence always have a preceding space.
Words in the middle of a sentence always have a trailing and preceding space.
Therefore, I would write my code as follows:
function containsWord(word, sentence) {
return (
sentence.startsWith(word.trim() + " ") ||
sentence.endsWith(" " + word.trim()) ||
sentence.includes(" " + word.trim() + " "));
}
console.log(containsWord("test", "This is a test of the containsWord function."));
Try the following -
var mainString = 'codehandbook'
var substr = /hand/
var found = substr.test(mainString)
if(found){
console.log('Substring found !!')
} else {
console.log('Substring not found !!')
}

Replace nth occurence of number in string with javascript [duplicate]

This question already has answers here:
Find and replace nth occurrence of [bracketed] expression in string
(4 answers)
Closed 5 years ago.
This question been asked before, but I did not succeed in solving the problem.
I have a string that contains numbers, e.g.
var stringWithNumbers = "bla_3_bla_14_bla_5";
I want to replace the nth occurence of a number (e.g. the 2nd) with javascript. I did not get farer than
var regex = new RegExp("([0-9]+)");
var replacement = "xy";
var changedString = stringWithNumbers.replace(regex, replacement);
This only changes the first number.
It was suggested to use back references like $1, but this did not help me.
The result should, for example, be
"bla_3_bla_xy_bla_5" //changed 2nd occurence
You may define a regex that matches all occurrences and pass a callback method as the second argument to the replace method and add some custom logic there:
var mystr = 'bla_3_bla_14_bla_5';
function replaceOccurrence(string, regex, n, replace) {
var i = 0;
return string.replace(regex, function(match) {
i+=1;
if(i===n) return replace;
return match;
});
}
console.log(
replaceOccurrence(mystr, /\d+/g, 2, 'NUM')
)
Here, replaceOccurrence(mystr, /\d+/g, 2, 'NUM') takes mystr, searches for all digit sequences with /\d+/g and when it comes to the second occurrence, it replaces with a NUM substring.
var stringWithNumbers = "bla_3_bla_14_bla_5";
var n = 1;
var changedString = stringWithNumbers.replace(/[0-9]+/g,v => n++ == 2 ? "xy" : v);
console.log(changedString);

Case insensitive in regex with Javascript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Case insensitive regex in javascript
Right now I have this:
my_list.match(new RegExp("(?:^|,)"+my_name+"(?:,|$)")))
Which, given the following:
my_list = "dog, cat, boy"
my_name = "dog"
Would return true.
However if I have
my_list = "Dog,Cat,boy"
and
my_name = "boy"
The regex wouldn't match. How would I adapt in order to be able to match with case insensitive?
First off: Never build a regular expression from an unescaped variable. Use this function to escape all special characters first:
RegExp.quote = function(str) {
return str.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
};
It modifies the RegExp object, you need to include it just once. Now:
function stringContains(str, token) {
var
spaces = /^\s+|\s+$/g, // matches leading/trailing space
token = token.replace(spaces, ""), // trim the token
re = new RegExp("(?:^|,)\\s*" + RegExp.quote(token) + "\\s*(?:,|$)", "i");
return re.test(str);
}
alert( stringContains("dog, cat, boy", " Dog ") );
Note
The "i" that makes the new RegExp case-insenstive.
The two added \s* that allow white-space before/after the comma.
The fact that "(?:^|,)\\s*" is correct, not "(?:^|,)\s*"" (in a JS string all backslashes need to be escaped).

Categories

Resources