JS - Remove all spaces and insert space three characters from end - javascript

I'm trying to format postcode entries in a form correctly so that they have a space in the correct location, which is always three characters from the end. E.g.:
AA1 1AA
A1A 1AA
AA11 1AA
A1 1AA
const addSpace = (str, fromEnd) => `${str.slice(0, -1 * fromEnd)} ${str.slice(-1 * fromEnd)}`;
['word', 'longword'].forEach(word => console.log(addSpace(word, 3)));
var el = document.getElementById('input_1_14');
el.addEventListener('keyup', function () {
this.value = addSpace(this.value, 3);
});
However, if I type a series of characters into the relevant field it is inserting spaces every other character, in addition to one three characters from the end, e.g.:
1 1 1 1 1 1 111
Where am I going wrong?

It is becous of the event onKeyUp, you place an extra letter and it keeps adding spaces after every event without removing them.
const addSpace = (str, fromEnd) => `${str.slice(0, -1 * fromEnd)} ${str.slice(-1 * fromEnd)}`;
const removeSpace = (str) => str.replace(/ /g, "");
const editString = (str, fromEnd) => addSpace(removeSpace(str), fromEnd);
['word', 'longword'].forEach(word => console.log(editString(word, 3)));
var el = document.getElementById('input_1_14');
el.addEventListener('keyup', function () {
this.value = editString(this.value, 3);
});
<input type="tex" id="input_1_14">

Try This
function addSpace(str,fromEnd) {
var result ='';
fromEnd += 1;
for (i=0;i<str.length;i++) {
if (i >= str.length - fromEnd) {
result += str[i]+' ';
} else if (str[i] == ' '){
continue;
} else {
result += str[i];
}
}
return result;
}
['word', 'longword'].forEach(word => console.log(addSpace(word, 3)));
var el = document.getElementById('input_1_14');
el.addEventListener('keyup', function () {
this.value = addSpace(this.value, 3);
});
It Is Now Fully Compatible With Your Code Just Replace It With Your Code And It Will Work

Related

Adding numeric values in a string together

I have a string returned from an endpoint in which I need to add certain parts of the string together in order to produce two different values.
Example response:
149,226;147,226;146,224
Now I know I can use the unary plus operator to force the string to be treated as a number like so.
var num1 = '20',
num2 = '22';
var total = (+num1) + (+num2);
or I could do some conversion like so
var number1 = parseInt(num1);
var number2 = parseInt(num2);
var total = number1 + number2;
either of these work fine however this is not what I am looking for exactly.
I want to take this result
149,226;147,226;146,224
Then add all the numbers before the first comer together so that would be (149, 147, 146) to produce one result and then add all the number after the second comer together (226, 226, 224).
I know I probably need some sort of reg expression for this I just dont know what.
You can just use string.split, twice, one for the ; and then again for the ,. And put this through array.reduce.
eg.
var str = '149,226;147,226;146,224';
var result = str.split(';')
.reduce((a,v) => {
var vv = v.split(',');
a[0] += vv[0] | 0;
a[1] += vv[1] | 0;
return a;
}, [0, 0]);
console.log(result);
For a more generic solution, that could handle any number of sub strings, eg. 1,2,3;4,5,6, and also handle alternative split types, and cope with extra , or ;.
function sumStrings(str, outerSplit, innerSplit) {
return str.split(outerSplit || ';')
.filter(Boolean)
.reduce((a,v) => {
v.split(innerSplit || ',')
.filter(Boolean)
.forEach((v,ix) => {
a[ix] = (a[ix] | 0) + (v | 0);
});
return a;
}, []);
}
console.log(sumStrings(
'149,226;147,226;146,224'
));
console.log(sumStrings(
'149.226.201|147.226.112.|146.224.300|',
'|','.'));
//how about total of totals?
console.log(sumStrings(
'149,226;147,226;146,224'
).reduce((a,v) => a + v));
.as-console-wrapper {
min-height: 100%
}
You could do:
const myString = '149,226;147,226;146,224';
/*
* 1. you split the string by ';' to obtain an array of string couples
* then you split each couple by ','. In this way you end up with an array like this:
* [['149', '266'], ['147', '266'], ['146', '264']]
*/
const myNumbers = myString.split(';').map(numCouple => numCouple.split(','));
/*
* 2. you use Array.prototype.reduce() to calculate the sums
*/
const sum1 = myNumbers.reduce((sum, item) => {
return sum += parseInt(item[0]);
}, 0);
const sum2 = myNumbers.reduce((sum, item) => {
return sum += parseInt(item[1]);
}, 0);
// or, as an alternative:
const sumsObj = myNumbers.reduce((obj, item) => {
obj.sum1 += parseInt(item[0]);
obj.sum2 += parseInt(item[1]);
return obj;
}, { sum1: 0, sum2: 0 });
// or also:
const sumsArr = myNumbers.reduce((acc, item) => {
acc[0] += parseInt(item[0]);
acc[1] += parseInt(item[1]);
return acc;
}, [0, 0]);
// test
console.log('sum1:', sum1);
console.log('sum2:', sum2);
console.log('--------------');
console.log('sum1:', sumsObj.sum1);
console.log('sum2:', sumsObj.sum2);
console.log('--------------');
console.log('sum1:', sumsArr[0]);
console.log('sum2:', sumsArr[1]);
without using regex, one possible solution:
var c = '149,226;147,226;146,224'
var d = c.split(";")
var first = d.map(x=>Number(x.split(",")[0]))
var second= d.map(x=>Number(x.split(",")[1]))
console.log(first)
console.log(second)
let resultFirst = first.reduce((a,b) => a + b, 0);
let resultSecond = second.reduce((a,b) => a + b, 0);
console.log(resultFirst)
console.log(resultSecond)
Below supplies regex to String's .split to get the numbers by themselves. Then you could add every other number but I don't see why not just add them all in order.
const str = '149,226;147,226;146,224'
const total = str.split(/[;,]/).map(Number).reduce((a, b) => a + b)
console.log('total', total)
I got this one running:
const nums = ('149,226;147,226;146,224');
var firstNums = nums.match(/(?<=[0-9]*)[0-9]+(?=,)/gs);
var secondNums = nums.match(/(?<=[0-9]*)[0-9]+(?=;|$)/gs);
console.log(firstNums, secondNums);
let sumFirstNums = 0,
sumSecondNums = 0;
firstNums.map(x => {
sumFirstNums += +x;
})
console.log(sumFirstNums)
secondNums.map(x => {
sumSecondNums += +x;
})
console.log(sumSecondNums)
//If you want the result in the same format:
const finalResult = `${sumFirstNums}, ${sumSecondNums};`
console.log(finalResult)
;)
For that string format, you could use a single pattern with 2 capturing groups matching 1+ more digits between a comma, and asserting a ; or the end of the string at the right.
You refer to the group values by indexing into the match of every iteration.
(\d+),(\d+)(?=;|$)
The pattern matches
(\d+) Capture group 1, match 1+ digits
, Match a comma
(\d+) Capture group 2, match 1+ digits
(?=;|$) Positive lookahead, assert directly to the right a ; or end of the string
See a regex demo.
let result1 = 0;
let result2 = 0
for (const match of "149,226;147,226;146,224".matchAll(/(\d+),(\d+)(?=;|$)/g)) {
result1 += +match[1]
result2 += +match[2]
}
console.log(result1, result2);

How to compare strings where a symbol equals more then one value. Javascript

So the issue is that I have 2 strings. One string is a random assortment of letters. The second is either a +,*,$ or {N}. Where the + sign represents all 26 letters, the $ represents numbers 1-9, the asterisk represents any 3 repeating characters unless show differently by {N}.
example:
input: "+++++*" "abcdehhhhhh"
output: false
input: "$**+*{2}" "9mmmrrrkbb"
output: true
Test question I got wrong, just tryna understand the answer.
The code below gives you your answer, although, it is a modifucation of the code above
function StringChallenge(str) {
// code goes here
let wordsArr = str.split(" ");
function re(pattern) {
let capture = 1;
const source = pattern
.replace(/([+*$])(?:\{(\d+)\})?/g, (match, rule, repeat = 3) => {
switch (rule) {
case "+":
return "[a-z]";
case "*":
return `(.)\\${capture++}{${repeat - 1}}`;
case "$":
return "\\d";
}
})
.replace(/(.+?)\1+/g, (match, capture) => {
const rle = `(?:${capture}){${match.length / capture.length}}`;
return rle.length < match.length ? rle : match;
});
return new RegExp(`^${source}$`);
}
function compare(pattern, input) {
const result = re(pattern).test(input);
return result;
}
return compare(wordsArr[0], wordsArr[1]);
}
console.log(StringChallenge("$**+*{2} 9mmmrrrkbb"));
console.log(StringChallenge("$**{2} ammmrrbb"));
I would approach this by iterating over the pattern and keeping a pointer to where in the string we're checking right now. That way you can move the pointer more or less by what N is in {N} (defaulting to 3); In each case I simply return false if the character isn't in the allowed set, and for * I figure out how many times the current character should be repeated and check if the next N characters equal input[x].repeat(N) (the current character repeated N times).
You can definitely do this with regex as well, but I honestly feel like it would end up being more complicated due to the need to translate each character to a class or repeat match.
function matchPattern(input, pattern) {
let x = 0; //pointer to input string
for(let i = 0; i < pattern.length; i++) {
switch(pattern[i]) {
case '+':
if(!'abcdefghijklmnopqrstuvwxyz'.includes(input[x++])) return false;
break;
case '$':
if(!'0123456789'.includes(input[x++])) return false;
break;
case '*':
let repeatNum = 3;
if(pattern[i+1] == '{' && pattern[i+3] == '}') repeatNum = +pattern[i+2];
if(input[x].repeat(repeatNum) != input.slice(x,x+=repeatNum)) return false;
break;
}
}
return x >= input.length;
}
console.log(matchPattern("abcdehhhhhh", "+++++*"));
console.log(matchPattern("9mmmrrrkbb", "$**+*{2}"));
We can convert the pattern string into a regular expression with String.prototype.replace() and the RegExp constructor, then use RegExp.prototype.test() to compare against the input string:
function re(pattern) {
let capture = 1;
const source = pattern.replace(
/([+*$])(?:\{(\d+)\})?/g,
(match, rule, repeat = 3) => {
switch (rule) {
case '+': return '[a-z]';
case '*': return `(.)\\${capture++}{${repeat - 1}}`;
case '$': return '\\d';
}
}
);
// the generated regular expression
console.log(source);
return new RegExp(`^${source}$`);
}
function compare(input, pattern) {
const result = re(pattern).test(input);
console.log(`'${input}' matches '${pattern}': ${result}`);
return result;
}
compare('abcdehhhhhh', '+++++*');
compare('9mmmrrrkbb', '$**+*{2}');
Notice that the generated regular expressions can potentially be long and repetitive, so we can encode repeating rules within the source of the regular expression using quantifiers as well:
function re(pattern) {
let capture = 1;
const source = pattern.replace(
/([+*$])(?:\{(\d+)\})?/g,
(match, rule, repeat = 3) => {
switch (rule) {
case '+': return '[a-z]';
case '*': return `(.)\\${capture++}{${repeat - 1}}`;
case '$': return '\\d';
}
}
).replace(
/(.+?)\1+/g,
(match, capture) => {
const rle = `(?:${capture}){${match.length / capture.length}}`;
// only replace it if the rle is actually shorter
return rle.length < match.length ? rle : match;
}
);
// the generated regular expression
console.log(source);
return new RegExp(`^${source}$`);
}
function compare(input, pattern) {
const result = re(pattern).test(input);
console.log(`'${input}' matches '${pattern}': ${result}`);
return result;
}
compare('abcdehhhhhh', '+++++*');
compare('9mmmrrrkbb', '$**+*{2}');
This is how i did it using php
<?php
/******
* This is a Jawaker Assesment from Coderbyte.com
* level HARD
*
* Task: StringChallenge(str)
*
* Have the function StringChallenge(str) read str
* which will contain two strings separated by a space.
* The first string will consist of the following sets of characters: +, *, $, and {N} which is optional.
* The plus (+) character represents a single alphabetic character,
* the ($) character represents a number between 1-9,
* and the asterisk (*) represents a sequence of the same character of length 3 unless it is followed by {N}
* which represents how many characters should appear in the sequence where N will be at least 1.
* Your goal is to determine if the second string exactly matches the pattern of the first string in the input.
* For example: if str is "++*{5} jtggggg" then the second string in this case does match the pattern,
* so your program should return the string true.
* If the second string does not match the pattern your program should return the string false.
* Examples
* Input: "+++++* abcdehhhhhh"
* Output: false
* Input: "$**+*{2} 9mmmrrrkbb"
* Output: true
*
*/
$str = "+++++***{2}+ abcdehhhhhhxxx"; //true
$str1 = "++*{4} 23ssss"; //true
$str2 = "++$$*++**{2} we23pppreeeeww"; //true
$str3 = "+++++* abcdehhhhhh"; //false
function StringChallenge($str)
{
//First thing we do here is to sperate the two strings in one array.
$exploded = explode(' ', $str);
//We count the elements inside the array.
$countExploded = count($exploded);
//If it's two strings then we are good.
if ($countExploded > 2) return false;
$firstString = $exploded[0];
$secondString = $exploded[1];
//Then we seperate each character from each string into two arrays.
$splitFirst = str_split($firstString);
$splitSecond = str_split($secondString);
//We loop inside the first array(first string where the pattren with this following logic)
//$i is for looping inside the first string, $j for looping inside the second string
//I solved this by making a point system and it goes like this:
//I take each character from first string and check what it's.
//If it's a (+) and it's a letter in the first character from second string then we can move to check the next character.
//And we add 1 to each matching pattren with a character.
// j for counting characters second string.
$j = 0;
//Point checker
$pointCheck = 0;
for ($i = 0;$i < count($splitFirst);$i++)
{
//To avoid "warning undefined array key"
if ($i < count($splitFirst) && $i + 1 != count($splitFirst))
{
if ($splitFirst[$i] == '*')
{
//Check if '*' is not the last character.
//Check if after the * there is a { and Check if after the number there is a }
if ($splitFirst[$i + 1] == '{' && preg_match('/[0-9]/', $splitFirst[$i + 2]) && $splitFirst[$i + 3] == '}')
{
$number = $splitFirst[$i + 2];
$pointCheck = $pointCheck + $number;
}
}
if ($splitFirst[$i] == '*' && $splitFirst[$i + 1] != '{')
{
$secondLetter = $j + 1;
$thirdLetter = $j + 2;
//Check if the $j is not the last character , this line of code to not fall in warning Undifinded Array;
if ($thirdLetter < count($splitSecond))
{
if ($splitSecond[$j] == $splitSecond[$secondLetter] && $splitSecond[$secondLetter] == $splitSecond[$thirdLetter])
{
$j = $j + 3;
$pointCheck = $pointCheck + 3;
}
}
}
}
if ($splitFirst[$i] == '+' && preg_match("/[a-z]/", $splitSecond[$j]))
{
$j++;
$pointCheck++;
}
elseif ($splitFirst[$i] == '+' && !preg_match("/[a-z]/", $splitSecond[$j]))
{
$pointCheck++;
}
if ($splitFirst[$i] == '$' && preg_match('/[0-9]/', $splitSecond[$j]))
{
$j++;
$pointCheck++;
}
elseif ($splitFirst[$i] == '$' && !preg_match('/[0-9]/', $splitSecond[$j]))
{
$pointCheck++;
}
}
if (count($splitSecond) == $pointCheck)
{
return "true";
}
else
{
return "false";
}
}
echo StringChallenge($str3);

Javascript: How can I loop through a word and slice off the characters after the first vowel?

I am trying to make a function that loops through a word, identifies the first vowel found (if any) in the word, and then splits up the word after the vowel.
example input: 'super'
example output: 'su', 'per'
function consAy(word){
if(word[i].indexOf("a" >= 0) || word[i].indexOf("e" >= 0) || word[i].indexOf("i" >= 0) || word[i].indexOf("o" >= 0) || word[i].indexOf("u" >= 0)){
}
One way to do it is to use a regular expression to .match() the pattern you are looking for:
function consAy(word){
var result = word.match(/^([^aeiou]*[aeiou])(.+)$/i)
return result ? result.slice(1) : [word]
}
console.log( consAy('super') )
console.log( consAy('AMAZING') )
console.log( consAy('hi') )
console.log( consAy('why') )
The function I've shown returns an array. If there was a vowel that was not at the end then the array has two elements. If there was only a vowel at the end, or no vowel, then the array has one element that is the same as the input string.
A brief breakdown of the regex /^([^aeiou]*[aeiou])(.+)$/i:
^ // beginning of string
[^aeiou]* // match zero or more non-vowels
[aeiou] // match any vowel
.+ // match one or more of any character
$ // end of string
...where the parentheses are used to create capturing groups for the two parts of the string we want to separate, and the i after the / makes it case insensitive.
The .match() method returns null if there was no match, so that's what the ternary ?: expression is for. You can tweak that part if you want a different return value for the case where there was no match.
EDIT: I was asked for a non-regex solution. Here's one:
function consAy(word){
// loop from first to second-last character - don't bother testing the last
// character, because even if it's a vowel there are no letters after it
for (var i = 0; i < word.length - 1; i++) {
if ('aeiou'.indexOf(word[i].toLowerCase()) != -1) {
return [word.slice(0, i + 1), word.slice(i + 1)]
}
}
return [word]
}
console.log( consAy('super') )
console.log( consAy('AMAZING') )
console.log( consAy('hi') )
console.log( consAy('why') )
This assumes a reasonably modern browser, or Node.
const string = "FGHIJK";
const isVowel = c => c.match(/[AEIOU]/i);
const pos = [...string].findIndex(isVowel);
const truncatedString = `${[...string].slice(0, pos + 1)}`;
truncatedString; // "FGHI"
Edit
As has been pointed out, the above is significantly more hassle than it's worth. Without further ado, a much saner approach.
const string = "FGHIJK";
const vowels = /[aeiou]/i;
const truncateAfter = (string, marker) => {
const pos = string.search(marker);
const inString = pos >= 0;
return string.slice(0, inString ? pos : string.length);
};
const truncated = truncateAfter(string, vowels);
Without using a RegEx of any kind. Ye ole fashioned algorithm.
const truncateAfter = (string, markers) => {
let c = "";
let buffer = "";
for (let i = 0, l = string.length; i < l; i += 1) {
c = string[i];
buffer += c;
if (markers.includes(c)) {
break;
}
}
return buffer;
};
const truncatedString = truncateAfter(
"XYZABC",
["A", "E", "I", "O", "U"],
);
With RegEx golf.
const string = "BCDEFG";
const truncatedString = string.replace(/([aeiou]).*/i, "$1");
With a reduction.
const isVowel = c => /[aeiou]/i.test(c);
const last = str => str[str.length - 1];
const truncatedString = [...string].reduce((buffer, c) =>
isVowel(last(buffer)) ? buffer : buffer + c, "");
Via a dirty filter hack, that takes way too much power O(n**2).
const truncatedString = [...string]
.filter((_, i, arr) => i <= arr.search(/[aeiou]/i));
There are others, but I think that's enough to shake the cobwebs out of my brain, for now.
I always like to take opportunities to write incomprehensible array-based code, so with that in mind...
const regexMatcher = pattern => input => {
return input.match(pattern)
};
const splitAtFirstMatch = matcher => arrayLike => {
return [...arrayLike]
.reduce(([pre, post, matchFound], element) => {
const addPre = matchFound || matcher(element);
return [
matchFound ? pre :[...pre, element],
matchFound ? [...post, element] : post,
addPre
];
}, [[],[], false])
.slice(0, 2)
.map(resultArrays => resultArrays.join(''));
};
console.log(splitAtFirstMatch(regexMatcher(/[aeiou]/))('super'));

String increment: increment the last string by one

the purpose of this code is to to write a function which increments a string, to create a new string. If the string already ends with a number, the number should be incremented by 1. If the string does not end with a number the number 1 should be appended to the new string. e.g. "foo123" --> "foo124" or "foo" --> "foo1".
With my code below, pretty much all my test cases are passed except a corner case for "foo999" did not print out "foo1000". I know that there should be a way to do with regex to fix my problem, but I am not too familiar with it. Can anyone please help?
function incrementString (input) {
var reg = /[0-9]/;
var result = "";
if(reg.test(input[input.length - 1]) === true){
input = input.split("");
for(var i = 0; i < input.length; i++){
if(parseInt(input[i]) === NaN){
result += input[i];
}
else if(i === input.length - 1){
result += (parseInt(input[i]) + 1).toString();
}
else{
result += input[i];
}
}
return result;
}
else if (reg.test(input[input.length - 1]) === false){
return input += 1;
}
}
You can use replace with a callback:
'foo'.replace(/(\d*)$/, function($0, $1) { return $1*1+1; });
//=> "foo1"
'foo999'.replace(/(\d*)$/, function($0, $1) { return $1*1+1; });
//=> "foo1000"
'foo123'.replace(/(\d*)$/, function($0, $1) { return $1*1+1; });
//=> "foo124"
Explanation:
/(\d*)$/ # match 0 or more digits at the end of string
function($0, $1) {...} # callback function with 2nd parameter as matched group #1
return $1*1+1; # return captured number+1. $1*1 is a trick to convert
# string to number
The most concise way that also accounts for leading zeros, non-numeric endings, and empty strings I've seen is:
''.replace(/[0-8]?9*$/, w => ++w)
//=> 1
'foo'.replace(/[0-8]?9*$/, w => ++w)
//=> foo1
'foo099'.replace(/[0-8]?9*$/, w => ++w)
//=> foo100
'foo999'.replace(/[0-8]?9*$/, w => ++w)
//=> foo1000
function pad(number, length, filler) {
number = number + "";
if (number.length < length) {
for (var i = number.length; i < length; i += 1) {
number = filler + number;
}
}
return number;
}
function incrementString (input) {
var orig = input.match(/\d+$/);
if (orig.length === 1) {
orig = pad(parseInt(orig[0]) + 1, orig[0].length, '0');
input = input.replace(/\d+$/, orig);
return input;
}
return input + "1";
}
What does it do?
It first checks if there is a trailing number. If yes, increment it and pad left it with zeros (with the function "pad" which you'd be able to sort it out yourself).
string.replace is a function which works with argument 1 the substring to search (string, regex), argument 2 the element to replace with (string, function).
In this case I've used a regex as first argument and the incremented, padded number.
The regex is pretty simple: \d means "integer" and + means "one or more of the preceeding", which means one or more digits. $ means the end of the string.
More info about regular expressions (in JavaScript): https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/RegExp (thanks #Casimir et Hippolyte for the link)
I think you can simplify your code greatly:
function incrementString(input) {
var splits = input.split(/(\d+)$/),
num = 1;
if (splits[1] !== undefined) num = parseInt(splits[1]) + 1;
return splits[0] + num;
}
This checks for any number of digits at the end of your string.
function incrementString (strng) {
//separateing number from string
let x = (strng).replace( /^\D+/g, '');
//getting the length of original number from the string
let len = x.length;
//getting the string part from strng
str = strng.split(x);
//incrementing number by 1
let number = Number(x) + 1 + '';
//padding the number with 0 to make it's length exactly to orignal number
while(number.length < len){
number = '0' + number;
}
//new string by joining string and the incremented number
str = (str + number).split(',').join('');
//return new string
return str;
}
My quick answer will be :
let newStr = string.split('');
let word = [];
let num = [];
for (let i = 0 ; i<string.length ;i++){
isNaN(string[i])? word.push(string[i]) : num.push(string[i])
}
let l=num.length-1;
let pureNum=0;
for (let i = 0 ; i<num.length ;i++){
pureNum += num[i] * Math.pow(10,l);
l--;
}
let wordNum = (pureNum+1).toString().split('');
for (let i = wordNum.length ; i<num.length ;i++){
wordNum.unshift("0");
}
return word.join("")+wordNum.join("");
}

How to count string occurrence in string?

How can I count the number of times a particular string occurs in another string. For example, this is what I am trying to do in Javascript:
var temp = "This is a string.";
alert(temp.count("is")); //should output '2'
The g in the regular expression (short for global) says to search the whole string rather than just find the first occurrence. This matches is twice:
var temp = "This is a string.";
var count = (temp.match(/is/g) || []).length;
console.log(count);
And, if there are no matches, it returns 0:
var temp = "Hello World!";
var count = (temp.match(/is/g) || []).length;
console.log(count);
/** Function that count occurrences of a substring in a string;
* #param {String} string The string
* #param {String} subString The sub string to search for
* #param {Boolean} [allowOverlapping] Optional. (Default:false)
*
* #author Vitim.us https://gist.github.com/victornpb/7736865
* #see Unit Test https://jsfiddle.net/Victornpb/5axuh96u/
* #see https://stackoverflow.com/a/7924240/938822
*/
function occurrences(string, subString, allowOverlapping) {
string += "";
subString += "";
if (subString.length <= 0) return (string.length + 1);
var n = 0,
pos = 0,
step = allowOverlapping ? 1 : subString.length;
while (true) {
pos = string.indexOf(subString, pos);
if (pos >= 0) {
++n;
pos += step;
} else break;
}
return n;
}
Usage
occurrences("foofoofoo", "bar"); //0
occurrences("foofoofoo", "foo"); //3
occurrences("foofoofoo", "foofoo"); //1
allowOverlapping
occurrences("foofoofoo", "foofoo", true); //2
Matches:
foofoofoo
1 `----´
2 `----´
Unit Test
https://jsfiddle.net/Victornpb/5axuh96u/
Benchmark
I've made a benchmark test and my function is more then 10 times
faster then the regexp match function posted by gumbo. In my test
string is 25 chars length. with 2 occurences of the character 'o'. I
executed 1 000 000 times in Safari.
Safari 5.1
Benchmark> Total time execution: 5617 ms (regexp)
Benchmark> Total time execution: 881 ms (my function 6.4x faster)
Firefox 4
Benchmark> Total time execution: 8547 ms (Rexexp)
Benchmark> Total time execution: 634 ms (my function 13.5x faster)
Edit: changes I've made
cached substring length
added type-casting to string.
added optional 'allowOverlapping' parameter
fixed correct output for "" empty substring case.
Gist
https://gist.github.com/victornpb/7736865
function countInstances(string, word) {
return string.split(word).length - 1;
}
console.log(countInstances("This is a string", "is"))
You can try this:
var theString = "This is a string.";
console.log(theString.split("is").length - 1);
My solution:
var temp = "This is a string.";
function countOccurrences(str, value) {
var regExp = new RegExp(value, "gi");
return (str.match(regExp) || []).length;
}
console.log(countOccurrences(temp, 'is'));
You can use match to define such function:
String.prototype.count = function(search) {
var m = this.match(new RegExp(search.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "g"));
return m ? m.length:0;
}
Just code-golfing Rebecca Chernoff's solution :-)
alert(("This is a string.".match(/is/g) || []).length);
The non-regex version:
var string = 'This is a string',
searchFor = 'is',
count = 0,
pos = string.indexOf(searchFor);
while (pos > -1) {
++count;
pos = string.indexOf(searchFor, ++pos);
}
console.log(count); // 2
String.prototype.Count = function (find) {
return this.split(find).length - 1;
}
console.log("This is a string.".Count("is"));
This will return 2.
Here is the fastest function!
Why is it faster?
Doesn't check char by char (with 1 exception)
Uses a while and increments 1 var (the char count var) vs. a for loop checking the length and incrementing 2 vars (usually var i and a var with the char count)
Uses WAY less vars
Doesn't use regex!
Uses an (hopefully) highly optimized function
All operations are as combined as they can be, avoiding slowdowns due to multiple operations
String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};
Here is a slower and more readable version:
String.prototype.timesCharExist = function ( chr ) {
var total = 0, last_location = 0, single_char = ( chr + '' )[0];
while( last_location = this.indexOf( single_char, last_location ) + 1 )
{
total = total + 1;
}
return total;
};
This one is slower because of the counter, long var names and misuse of 1 var.
To use it, you simply do this:
'The char "a" only shows up twice'.timesCharExist('a');
Edit: (2013/12/16)
DON'T use with Opera 12.16 or older! it will take almost 2.5x more than the regex solution!
On chrome, this solution will take between 14ms and 20ms for 1,000,000 characters.
The regex solution takes 11-14ms for the same amount.
Using a function (outside String.prototype) will take about 10-13ms.
Here is the code used:
String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};
var x=Array(100001).join('1234567890');
console.time('proto');x.timesCharExist('1');console.timeEnd('proto');
console.time('regex');x.match(/1/g).length;console.timeEnd('regex');
var timesCharExist=function(x,c){var t=0,l=0,c=(c+'')[0];while(l=x.indexOf(c,l)+1)++t;return t;};
console.time('func');timesCharExist(x,'1');console.timeEnd('func');
The result of all the solutions should be 100,000!
Note: if you want this function to count more than 1 char, change where is c=(c+'')[0] into c=c+''
var temp = "This is a string.";
console.log((temp.match(new RegExp("is", "g")) || []).length);
A simple way would be to split the string on the required word, the word for which we want to calculate the number of occurences, and subtract 1 from the number of parts:
function checkOccurences(string, word) {
return string.split(word).length - 1;
}
const text="Let us see. see above, see below, see forward, see backward, see left, see right until we will be right";
const count=countOccurences(text,"see "); // 2
I think the purpose for regex is much different from indexOf.
indexOf simply find the occurance of a certain string while in regex you can use wildcards like [A-Z] which means it will find any capital character in the word without stating the actual character.
Example:
var index = "This is a string".indexOf("is");
console.log(index);
var length = "This is a string".match(/[a-z]/g).length;
// where [a-z] is a regex wildcard expression thats why its slower
console.log(length);
Super duper old, but I needed to do something like this today and only thought to check SO afterwards. Works pretty fast for me.
String.prototype.count = function(substr,start,overlap) {
overlap = overlap || false;
start = start || 0;
var count = 0,
offset = overlap ? 1 : substr.length;
while((start = this.indexOf(substr, start) + offset) !== (offset - 1))
++count;
return count;
};
var myString = "This is a string.";
var foundAtPosition = 0;
var Count = 0;
while (foundAtPosition != -1)
{
foundAtPosition = myString.indexOf("is",foundAtPosition);
if (foundAtPosition != -1)
{
Count++;
foundAtPosition++;
}
}
document.write("There are " + Count + " occurrences of the word IS");
Refer :- count a substring appears in the string for step by step explanation.
Building upon #Vittim.us answer above. I like the control his method gives me, making it easy to extend, but I needed to add case insensitivity and limit matches to whole words with support for punctuation. (e.g. "bath" is in "take a bath." but not "bathing")
The punctuation regex came from: https://stackoverflow.com/a/25575009/497745 (How can I strip all punctuation from a string in JavaScript using regex?)
function keywordOccurrences(string, subString, allowOverlapping, caseInsensitive, wholeWord)
{
string += "";
subString += "";
if (subString.length <= 0) return (string.length + 1); //deal with empty strings
if(caseInsensitive)
{
string = string.toLowerCase();
subString = subString.toLowerCase();
}
var n = 0,
pos = 0,
step = allowOverlapping ? 1 : subString.length,
stringLength = string.length,
subStringLength = subString.length;
while (true)
{
pos = string.indexOf(subString, pos);
if (pos >= 0)
{
var matchPos = pos;
pos += step; //slide forward the position pointer no matter what
if(wholeWord) //only whole word matches are desired
{
if(matchPos > 0) //if the string is not at the very beginning we need to check if the previous character is whitespace
{
if(!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>?#\[\]^_`{|}~]/.test(string[matchPos - 1])) //ignore punctuation
{
continue; //then this is not a match
}
}
var matchEnd = matchPos + subStringLength;
if(matchEnd < stringLength - 1)
{
if (!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>?#\[\]^_`{|}~]/.test(string[matchEnd])) //ignore punctuation
{
continue; //then this is not a match
}
}
}
++n;
} else break;
}
return n;
}
Please feel free to modify and refactor this answer if you spot bugs or improvements.
For anyone that finds this thread in the future, note that the accepted answer will not always return the correct value if you generalize it, since it will choke on regex operators like $ and .. Here's a better version, that can handle any needle:
function occurrences (haystack, needle) {
var _needle = needle
.replace(/\[/g, '\\[')
.replace(/\]/g, '\\]')
return (
haystack.match(new RegExp('[' + _needle + ']', 'g')) || []
).length
}
Try it
<?php
$str = "33,33,56,89,56,56";
echo substr_count($str, '56');
?>
<script type="text/javascript">
var temp = "33,33,56,89,56,56";
var count = temp.match(/56/g);
alert(count.length);
</script>
Simple version without regex:
var temp = "This is a string.";
var count = (temp.split('is').length - 1);
alert(count);
No one will ever see this, but it's good to bring back recursion and arrow functions once in a while (pun gloriously intended)
String.prototype.occurrencesOf = function(s, i) {
return (n => (n === -1) ? 0 : 1 + this.occurrencesOf(s, n + 1))(this.indexOf(s, (i || 0)));
};
function substrCount( str, x ) {
let count = -1, pos = 0;
do {
pos = str.indexOf( x, pos ) + 1;
count++;
} while( pos > 0 );
return count;
}
ES2020 offers a new MatchAll which might be of use in this particular context.
Here we create a new RegExp, please ensure you pass 'g' into the function.
Convert the result using Array.from and count the length, which returns 2 as per the original requestor's desired output.
let strToCheck = RegExp('is', 'g')
let matchesReg = "This is a string.".matchAll(strToCheck)
console.log(Array.from(matchesReg).length) // 2
Now this is a very old thread i've come across but as many have pushed their answer's, here is mine in a hope to help someone with this simple code.
var search_value = "This is a dummy sentence!";
var letter = 'a'; /*Can take any letter, have put in a var if anyone wants to use this variable dynamically*/
letter = letter && "string" === typeof letter ? letter : "";
var count;
for (var i = count = 0; i < search_value.length; count += (search_value[i++] == letter));
console.log(count);
I'm not sure if it is the fastest solution but i preferred it for simplicity and for not using regex (i just don't like using them!)
You could try this
let count = s.length - s.replace(/is/g, "").length;
We can use the js split function, and it's length minus 1 will be the number of occurrences.
var temp = "This is a string.";
alert(temp.split('is').length-1);
Here is my solution. I hope it would help someone
const countOccurence = (string, char) => {
const chars = string.match(new RegExp(char, 'g')).length
return chars;
}
var countInstances = function(body, target) {
var globalcounter = 0;
var concatstring = '';
for(var i=0,j=target.length;i<body.length;i++){
concatstring = body.substring(i-1,j);
if(concatstring === target){
globalcounter += 1;
concatstring = '';
}
}
return globalcounter;
};
console.log( countInstances('abcabc', 'abc') ); // ==> 2
console.log( countInstances('ababa', 'aba') ); // ==> 2
console.log( countInstances('aaabbb', 'ab') ); // ==> 1
substr_count translated to Javascript from php
Locutus (Package that translates Php to JS)
substr_count (official page, code copied below)
function substr_count (haystack, needle, offset, length) {
// eslint-disable-line camelcase
// discuss at: https://locutus.io/php/substr_count/
// original by: Kevin van Zonneveld (https://kvz.io)
// bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
// improved by: Brett Zamir (https://brett-zamir.me)
// improved by: Thomas
// example 1: substr_count('Kevin van Zonneveld', 'e')
// returns 1: 3
// example 2: substr_count('Kevin van Zonneveld', 'K', 1)
// returns 2: 0
// example 3: substr_count('Kevin van Zonneveld', 'Z', 0, 10)
// returns 3: false
var cnt = 0
haystack += ''
needle += ''
if (isNaN(offset)) {
offset = 0
}
if (isNaN(length)) {
length = 0
}
if (needle.length === 0) {
return false
}
offset--
while ((offset = haystack.indexOf(needle, offset + 1)) !== -1) {
if (length > 0 && (offset + needle.length) > length) {
return false
}
cnt++
}
return cnt
}
Check out Locutus's Translation Of Php's substr_count function
The parameters:
ustring: the superset string
countChar: the substring
A function to count substring occurrence in JavaScript:
function subStringCount(ustring, countChar){
var correspCount = 0;
var corresp = false;
var amount = 0;
var prevChar = null;
for(var i=0; i!=ustring.length; i++){
if(ustring.charAt(i) == countChar.charAt(0) && corresp == false){
corresp = true;
correspCount += 1;
if(correspCount == countChar.length){
amount+=1;
corresp = false;
correspCount = 0;
}
prevChar = 1;
}
else if(ustring.charAt(i) == countChar.charAt(prevChar) && corresp == true){
correspCount += 1;
if(correspCount == countChar.length){
amount+=1;
corresp = false;
correspCount = 0;
prevChar = null;
}else{
prevChar += 1 ;
}
}else{
corresp = false;
correspCount = 0;
}
}
return amount;
}
console.log(subStringCount('Hello World, Hello World', 'll'));
var str = 'stackoverflow';
var arr = Array.from(str);
console.log(arr);
for (let a = 0; a <= arr.length; a++) {
var temp = arr[a];
var c = 0;
for (let b = 0; b <= arr.length; b++) {
if (temp === arr[b]) {
c++;
}
}
console.log(`the ${arr[a]} is counted for ${c}`)
}

Categories