Count matches at the end of a string - javascript

I want to count the number of occurrences of a string at the end of the string. I want it to ignore occurrences that are not at the end and I want it to return zero if there are none.
terminal string to find: "-1"
e.g. string = 1
// 0
e.g. string = 1-1
// 1
e.g. string = 1-1-1
// 2
e.g. string = 1-2-1
// 1
e.g. string = 1-2-1-2-1
// 1
e.g. string = 2-1-1-1-1
// 4
e.g. string = 1-1-2
// 0
I want it to count all of the occurrences at the end of the string, not just the occurrences anywhere in the string.
I tried:
var occurrences = string.match(/(-1)*$/).length;
I have a JS Fiddle here: JS Fiddle
It returns "2", no matter what my string.

You need to work on the first element of the returned array:
string.match(/(-1)*$/)[0].length/2
Find the length of first element which is the matched string of "-1" at the end and divide by 2 since the string "-1" is of length 2.
To quote from MDN String.prototype.match():
Return value
If the string matches the expression, it will return an Array
containing the entire matched string as the first element, followed by
any results captured in parentheses. If there were no matches, null is
returned.
function count() {
console.log(string.match(/(-1)*$/)[0].length / 2)
}
var string = "1"
// 0
count();
string = "1-1"
// 1
count();
string = "1-1-1"
// 2
count();
string = "1-2-1"
// 1
count();
string = "1-2-1-2-1"
// 1
count();
string = "2-1-1-1-1"
// 4
count();
string = "1-1-2"
// 0
count();

Walk backwards and count?
var string = "2-1-1-1-1";
var find = "-1";
var match = 0;
for (var i = string.length; i >= 0; i -= find.length) {
if (string.substr(i - find.length, find.length) == find)
match++;
else
break;
}
console.log("="+match)

Use String#match to find the chain of -1 that reaches the end, then split by -1, and get the length -1. When you split an a string of -1-1-1 you'll get an array with four items. Now we can extract the length, and reduce it by one.
function m(str) {
return str.match(/(-1)*$/g)[0].split(-1).length - 1;
}
console.log(m('1')) // 0
console.log(m('1-1')) // 1
console.log(m('1-1-1')) // 2
console.log(m('1-2-1')) // 1
console.log(m('1-2-1-2-1')) // 1
console.log(m('2-1-1-1-1')) // 4
console.log(m('1-1-2')) // 0

Try this. This runs Ok for all of your tested values
function countOnesAtTheEnd(s){
var array = s.split("-");
var count = 0;
for(var i =1; i<array.length; i++)
{
if(array[i] =="1"){
count++;
}
else count = 0;
}
console.log(count);
}
countOnesAtTheEnd("1");
countOnesAtTheEnd("1-1");
countOnesAtTheEnd("1-1-1");
countOnesAtTheEnd("1-2-1");
countOnesAtTheEnd("1-2-1-2-1");
countOnesAtTheEnd("2-1-1-1-1");
countOnesAtTheEnd("1-1-2");

Non regex version:
var occurences = 0;
string.split("-1").reduceRight((exit, space) => {
if(exit || space) return true;
occurences++;
return false;
}, false);

Related

How to build a function that searches for string occurrences?

I need help Writing a function subLength() that takes 2 parameters, a string and a single character. The function should search the string for the two occurrences of the character and return the length between them including the 2 characters. If there are less than 2 or more than 2 occurrences of the character the function should return 0. How can I solve this problem using loops?
subLength('Saturday', 'a'); // returns 6
subLength('summer', 'm'); // returns 2
subLength('digitize', 'i'); // returns 0
subLength('cheesecake', 'k'); // returns 0
Here I loop through the characters of the string to find each value that is the char.
if the length isn't 2, return 0.
using slice, get only the characters within the two found indexs and get that length adding one to fix the offset
const subLength = (str, char) => {
let strChars = str.toLowerCase().split(""),
found = [],
length = 0;
strChars.forEach((val, index) => {
if (val === char) {
found.push(index);
}
});
if (found.length != 2) {
return length;
}
return str.slice(found[0], found[1]).length + 1;
}
console.log(subLength('Saturday', 'a')); // returns 6
console.log(subLength('summer', 'm')); // returns 2
console.log(subLength('digitize', 'i')); // returns 0
console.log(subLength('cheesecake', 'k')); // returns 0
You can try this logic:
Loop over string and count number of occurance
if count is 2,
Create a regex to capture the string in between.
Return its length
Else return 0
function subLength(str, char) {
let length = 0;
const occuranceCount = Array
.from(str)
.filter((c) => c.toLowerCase() === char.toLowerCase())
.length
if (occuranceCount === 2) {
const regex = new RegExp(`${char}(.*)${char}`)
length = str.match(regex)[0].length
}
console.log(length)
return length;
}
subLength('Saturday', 'a'); // returns 6
subLength('summer', 'm'); // returns 2
subLength('digitize', 'i'); // returns 0
subLength('cheesecake', 'k'); // returns 0
Using just for loop:
function subLength(str, char) {
let count = 0;
let initPosition;
let lastPosition;
for (let i = 0; i < str.length; i++) {
if (str[i] === char) {
count++
if (count > 2) {
return 0;
}
if (initPosition === undefined) {
initPosition = i
} else {
lastPosition = i+1
}
}
}
return count < 2 ? 0 : lastPosition - initPosition;
}
console.log(subLength('Saturday', 'a')); // returns 6
console.log(subLength('summer', 'm')); // returns 2
console.log(subLength('digitize', 'i')); // returns 0
console.log(subLength('cheesecake', 'k')); // returns 0
I too am going through the Codecademy course where this question came up which led me to this post.
Using the RegExp solution provided by #Rajesh (thank you!!) I started to break it down to better understand what was going on and making notes/comments because I am still pretty new and haven't used or been exposed to some of these things.
At the end of it all I thought I'd share what I ended up with in case anyone found it helpful.
function subLength(str, char) {
// Outputting to the console what we are looking for given the value of the string and character from the test cases at the end of this script.
console.log(`Showing the subLength for the string: "${str}" between "${char}" and "${char}" including the "${char}" positions.`);
// create the length variable which will be returned by the function
let length = 0;
// ** Search the string for the two occurrences of the character and count them. Then assign the result to the occurrenceCount variable for use in the if else statement.
// The "Array" class is a global object that is used in the construction off arrays.
// The Array.from() static method creates a new, shallow-copied Array instance from an array-like or iterable object.
// The Array.filter() method creates a new array with all elements that pass the test implemented by the provided function. The "c" represents each element of the array/string which is then compared to the char variable. if it is a match it gets added to the Array. We use .toLowerCase on both to ensure case compatibility.
// Appending the Array with ".length" assigns occurrenceCount the numeric value of the array's length rather than the array of characters.
const occurrenceCount = Array.from(str).filter((c) => c.toLowerCase() === char.toLowerCase());
console.log(' The contents of the occurrenceCountArray = ' + occurrenceCount);
console.log(' The character occurrence count = ' + occurrenceCount.length);
// if the string has two occurrences : return the length between them including the two characters : else the string has less than 2 or more than 2 characters : return 0.
if (occurrenceCount.length === 2) {
// The RegExp object is used for matching text with a pattern. The "(.*)" in between the ${char}'s will match and capture as much as possible aka greedy match. "()" = capture anything matched. (" = start of group. "." = match any character. "*" = Greedy match that matches everything in place of the "*". ")" = end of group.
const regex = new RegExp(`${char}(.*)${char}`);
// log to console the pattern being matched
console.log(` regex pattern to find = ${regex}`);
// log to the console the [0] = index 0 pattern that was captured from the string using str.match(regex)[0]
console.log(` regex output = ${str.match(regex)[0]}`);
// Use".length" to count the number of characters in the regex string at index 0 of the regex array and assign that value to the length variable.
length = str.match(regex)[0].length;
// Output the results to the console
console.log(` The distance from "${char}" to "${char}" (including the "${char}" positions) in the string: ${str} = ${length}\n`);
// return the length value
return length;
} else {
// Output the results to the console
console.log(` The string either has too many or too few occurrences.\n The subLength = ${length}\n`);
// return the length value
return length;
}
}
// test cases
subLength('Saturday', 'a'); // returns 6
subLength('summer', 'm'); // returns 2
subLength('digitize', 'i'); // returns 0
subLength('cheesecake', 'k'); // returns 0
The answer I am getting is this:
const subLength = (str, char) => {
let charCount = 0;
let len = -1;
for (let i=0; i<str.length; i++) {
if (str[i] == char) {
charCount++;
if (charCount > 2) {
return 0;
}
if (len == -1) {
len = i;
} else {
len = i - len + 1
}
}
}
if (charCount < 2) {
return 0;
}
return len;
};
It is better to try yourself a solution first. It is a very bad practice to just ask a solution for your homework!!!
Even if the solution can be JUST a few lines of code i wrote for you with commments a working solution :
const subLength = (str,char) => {
// create an empty array
const strarr = [];
// push string into array
strarr.push(str);
//initiate a count variable
let count = 0;
// WRITE YOUR REGULAR EXPRESSION
// Using the regular expression constructor - new RegExp("ab{2}", "g") .
const regString = `[${char}]`;
const regex = new RegExp(regString, "g");
// iterate through the string array to
for (let i = 0; i < strarr.length; i++) {
// calculate how many time the character occurs
count = (strarr[i].match(regex) || []).length;
};
// check with if condition
//if count is 2
if (count === 2) {
// calculate the index of first ocurrance of the string
first = str.indexOf(char);
// calculate the index of second ocurrance of the string
second = str.lastIndexOf(char);
// calculate the distance between them
return second - first + 1;
// if count is greater than two return 0
}
else if (count > 2) {
return count = 0;
}
// if count is less than two return 0
else if (count < 2) {
return 0;
}
};
console.log(subLength("iiiiliiile","l"));
I just answered this problem in codeAcademy and this is the solution that I came up with, just using if-statements and string.indexOf
const subLength = (strng, char) => {
let firstIndex = strng.indexOf(char);
let secondIndex = strng.indexOf(char, (firstIndex + 1));
let thirdIndex = strng.indexOf(char, (secondIndex + 1));
if (firstIndex === -1){
return 0
} else if (secondIndex === -1){
return 0
} else if (thirdIndex === -1 ){
return (secondIndex - firstIndex + 1)
} else {
return 0
};
};

Javascript: Get Length of a String without Length Propery, And with Slice

I know, it's a weird one! But why does this not work?
function getStringLength(string) {
// see how many substrings > 0 can be built
// log that number & return
var subString = string.slice();
var counter = 0;
while (subString !== '') {
counter++;
subString = subString.slice(counter);
}
return counter;
}
var output = getStringLength('hello');
console.log(output); // --> expecting 5, but getting 3 (??)
I really want to do it with slice! The original challenge was to not use the length property, and I figured this out, which works fine:
function getStringLength(string) {
var long = 0;
while (string[long] !== undefined) {
long++;
}
return long;
}
you were mutating your string, this should work for you
function getStringLength(string) {
// see how many substrings > 0 can be built
// log that number & return
var subString = string.slice();
var counter = 0;
while (subString !== '') {
counter++;
subString = subString.slice(1);
}
return counter;
}
var output = getStringLength('hello');
console.log(output); // 5
The main difference was that I was doing
subString = subString.slice(1);
instead of
subString = subString.slice(counter);
which always decreased length by 1
The problem is the code substring.slice(counter) First time, you chop off 1 character. Then you chop off 2 characters from the already-chopped substring. Either chop off 1 at a time, or chop off the increasing amount from the original string. So that's either substring.slice(1) or string.slice(counter)
function getStringLength(string) {
// see how many substrings > 0 can be built
// log that number & return
var subString = string.slice();
var counter = 0;
while (subString !== '') {
counter++;
subString = substring.slice(1);
}
return counter;
}
var output = getStringLength('hello');
console.log(output);
To achieve expected result, use below option
function getStringLength(arr){
return arr.lastIndexOf(arr.slice(-1))+1
}
var output = getStringLength('hello');
console.log(output);
https://codepen.io/nagasai/pen/gGPWEE?editors=1111
Option2: As type of array is object,below option works too
function getStringLength(arr){
return Object.keys(arr).pop()*1 + 1
}
var output = getStringLength('hello');
console.log(output);
https://codepen.io/nagasai/pen/PJZmgg?editors=1111
Check the below updated options to handle empty and numbers
https://codepen.io/nagasai/pen/GMoQgy?editors=1111
https://codepen.io/nagasai/pen/YrweWr?editors=1111
Perhaps a slightly shorter answer:
function getStringLength(string) {
var counter = 0;
while (string.slice(counter)) {
counter++;
}
return counter;
}
var outputHello = getStringLength('hello');
console.log(outputHello); // 5
var outputEmpty = getStringLength('');
console.log(outputEmpty); // 0

Permutations filtered with no repeating characters

This is a task from freeCodeCamp.
My goal is to create a function which:
Takes any string with any characters.
Creates an array with all the permutations possible out of that string.
Filters the array and returns only the strings which don't have repeated consecutive letters.
Return the number of total permutations of the provided string that don't have repeated consecutive letters. Assume that all characters in
the provided string are each unique. For example, aab should return 2
because it has 6 total permutations (aab, aab, aba, aba, baa, baa),
but only 2 of them (aba and aba) don't have the same letter (in this
case a) repeating.
I can't figure out what have i wrote wrong. I think the problem lies either in the filter function or the permutation list is faulty.
function permAlone(str) {
if (str.length == 1) {
return str;
}
// Creates all possible Permutations and pushes to an array
var arr = [];
var p = 0; // position of the element which needs to be swapped
// Loop count equal to number of Permutations.
var loops = factorialize(str.length);
for (var i = 0; i < loops; i++) {
// if the position is not the last element in the strig keep swapping with next following character
if (p != str.length - 1) {
var splitStr = str.split('')
arraySwapElements(splitStr, p, p + 1);
str = splitStr.join('');
arr.push(str);
p += 1;
// when position is at the last index, change position to 0
} else {
p = 0;
i -= 1;
}
}
// swaps 2 items in an array
function arraySwapElements(arr, a, b) {
var item = arr[a];
arr[a] = arr[b];
arr[b] = item;
};
// outputs a factorial of a number
function factorialize(num) {
if (num === 0) {
return 1;
} else {
return num * factorialize(num - 1);
}
}
// filters any array which has 2 or more repeating characters
var x = arr.filter(function(str) {
var re = /(.)\1+/;
var result = re.test(str);
if (!result) {
return str;
}
})
// returns the filtered arrays length
return x.length
}
console.log(permAlone('abfdefa'));
When testing:
permAlone("aab") should return a number. // Correct
permAlone("aab") should return 2. // Correct
permAlone("aaa") should return 0. // Correct
permAlone("aabb") should return 8. // Correct
permAlone("zzzzzzzz") should return 0.// Correct
permAlone("a") should return 1.// Correct
permAlone("aaab") should return 0.// Correct
permAlone("abcdefa") should return 3600. // Incorrect
permAlone("abfdefa") should return 2640.// Incorrect
permAlone("aaabb") should return 12. // Incorrect
The issue stems from the logic used in the for loop. While the loop does generate the right number of total permutations, it doesn't generate all permutations.
For example, if our string to be permuted was "abcd", the swapping mechanism would generate strings like this:
bacd bcad bcda
cbda cdba cdab
dcab dacb dabc
adbc abdc abcd
Uh oh! That last arrangement is the same as the starting string. When we start swapping again, we're going to get the same set that we did on the first pass. We're never going to get a permutation like "acbd". Thus the resulting array contains higher numbers of some permutations and lower numbers of others.
I'm not sure how to fix it with the approach you're using, but a recursive function to get permutations could be written like this:
// Returns an array of all permutations of a string
function getPerms(str) {
// Base case. If the string has only one element, it has only one permutation.
if (str.length == 1) {
return [str];
}
// Initialise array for storing permutations
let permutations = [];
// We want to find the permutations starting with each character of the string
for (let i = 0; i < str.length; i++) {
// Split the string to an array
let splitStr = str.split('');
// Pull out the character we're checking for permutations starting with
let currentElem = splitStr.splice(i, 1)[0];
// Get permutations of the remaining characters
let subPerms = getPerms(splitStr.join(''));
// Concat each of these permutations with the character we're checking
// Add them to our list
subPerms.forEach(function (combination) {
permutations.push(currentElem.concat(combination));
});
}
// return our list
return combinations;
}

How to separate these strings using javascript

I have collection of string like '36*' , '95' , '103*', '1001*' , '2301'.
I want to separate these into two parts the numerical part into integer and the asterisks part.
eg: take 36 from first, 95 from second, 103 from third and so on. I add them all. If asterisk is found then multiply the number with some factor.
The asterisk is always at the end.
You can extract out the parts you need using a regex.
var values = ['36*', '95', '103*', '1001*', '2301'];
var parts = values.map(function(x) {
var match = /(\d+)(\/|\*|\+|\-)?/.exec(x);
return {
numericPart: match[1],
operator: match[2]
};
});
You can then access the numeric or operator part for each element in your original array. i.e. parts[2].numericPart == 95
The regex (\d+)(\/|\*|\+|\-)? can be broken down as follows;
(\d+) - matches 1 or more digits and stores them in capture group 1
(\/|\*|\+|\-)? - matches a /*+- and stores it in capture group 2, this matches 0 or 1 times
This function will take an input and will return the number & special symbol(*).
function _seperateNum(value){
var returnObj={}; // This object will contain number * special character(if)
var replaceChar="";
if(value.indexOf("*") !=-1){ // check if input has *
replaceChar = value.replace(/[*]/g, ''); // replace it
returnObj.num = parseInt(replaceChar); // convert to number
returnObj.char = "*";
}
else{ // if no special charcater
returnObj.num = parseInt(value);
}
return returnObj;
}
var a =_seperateNum("36*");
console.log(a.num);
Jsfiddle
var
arr = ['36*' , '95' , '103*', '1001*' , '2301'],
sum = 0;
for (var i in arr) {
var item = arr[i];
sum += parseInt(item.indexOf('*') != -1 ? item.replace('*', '') : item);
}
alert(sum);
var arr = ['36*' , '95' , '103*', '1001*' , '2301'];
var t = [];
var f = [];
arr.forEach(function(e){if(e.indexOf("*") > 0){ t.push(e) } else { f.push(e) } } );
console.log(t); //asterisk values
#=> ["36*", "103*", "1001*"]
console.log(f); // other value
#=> ["95", "2301"]
if you want to multiple the each element of the array of asterisk elements to a factor like 10
arr.forEach(function(e){if(e.indexOf("*") > 0){ t.push(parseInt(e)* 10) } else { f.push(parseInt(e)) } } );
console.log(t); //asterisk values
#=> [360, 1030, 10010]
console.log(f); // other value
#=> [95, 2301]

Replace every nth character from a string

I have this JavaScript:
var str = "abcdefoihewfojias".split('');
for (var i = 0; i < str.length; i++) {
var xp = str[i] = "|";
}
alert( str.join("") );
I aim to replace every fourth letter in the string abcdefoihewfojias with |, so it becomes abc|efo|....etc,but I do not have a clue how to do this.
You could just do it with a regex replace:
var str = "abcdefoihewfojias";
var result = str.replace(/(...)./g, "$1|");
console.log(result);
To support re-usability and the option to wrap this in an object/function let's parameterise it:
var str = "abcdefoihewfojias".split('');
var nth = 4; // the nth character you want to replace
var replaceWith = "|" // the character you want to replace the nth value
for (var i = nth-1; i < str.length-1; i+=nth) {
str[i] = replaceWith;
}
alert( str.join("") );
This might help you solve your problem
var str = "abcdefoihewfojias".split("");
for (var i = 3; i < str.length - 1; i+=4) {
str[i] = "|";
}
alert( str.join("") );
You go with for loop from the the first char that you want to replace (the 3 char) until the one digit before the end and replace every 4 places.
If the for loop will go from the str.length and not to str.length-1 sometimes at the last char will be |.
.map one-liner
You can use this one-liner:
var str = "abcdefoihewfojias";
str.split('').map(function(l,i) {
return (i + 1) % 4 ? l : '|';
}).join('');
% returns the remainder. So:
# | Result (# + 1) % 4
---|-------
0 | 1
1 | 2
2 | 3
4 | 0 // Bingo!
ES6 alternative
With ES6, you can do:
[...str].map((l,i) => (i + 1) % 4 ? l : '|')
Simple just use modulus
https://jsfiddle.net/ctfsorwg/
var str = "abcdefoihewfojias";
var outputStr = str.split("");
for (var i = 0; i < outputStr.length; i++) {
if(!((i+1)%4))outputStr[i] = '|';
}
alert( "Before: " + str + "\nAfter: " + outputStr.join(""));
While there are several answers already, I thought I'd offer a slightly alternative approach, using Array.prototype.map(), wrapped in a function that can be adapted by the user (to update the value of n in the nth character, and change the replacement character used):
// defining the named function, with an 'opts' argument:
function replaceNthWith(opts) {
// setting the default options:
var defaults = {
// defining the nth character, in this case
// every fourth:
'nth': 4,
// defining the character to replace that
// nth character with:
'char': '|'
};
// Note that there's no default string argument,
// so that one argument must be provided in the
// opts object.
// iterating over each property in the
// opts Object:
for (var property in opts) {
// if the current property is a property of
// this Object, not inherited from the Object
// prototype:
if (opts.hasOwnProperty(property)) {
// we set that property of the defaults
// Object to be equal to that property
// as set in the opts Object:
defaults[property] = opts[property];
}
}
// if there is a defaults.string property
// (inherited from the opts.string property)
// then we go ahead; otherwise nothing happens
// note: this property must be set for the
// function to do anything useful:
if (defaults.string) {
// here we split the string supplied from the user,
// via opts.string, in defaults.string to form an
// Array of characters; we iterate over that Array
// with Array.prototype.map(), which process one
// Array and returns a new Array according to the
// anonymous function supplied:
return haystack = defaults.string.split('').map(function(character, index) {
// here, when the index of the current letter in the
// Array formed by Array.prototype.split() plus 1
// (JavaScript is zero-based) divided by the number
// held in defaults.nth is equal to zero - ensuring
// that the current letter is the 'nth' index we return
// the defaults.char character; otherwise we return
// the original character from the Array over which
// we're iterating:
return (index + 1) % parseInt(defaults.nth) === 0 ? defaults.char : character;
// here we join the Array back into a String, using
// Array.prototype.join() with an empty string:
}).join('');
}
}
// 'snippet.log()' is used only in this demonstration, in real life use
// 'console.log()', or print to screen or display in whatever other
// method you prefer:
snippet.log( replaceNthWith({ 'string': "abcdefoihewfojias" }) );
function replaceNthWith(opts) {
var defaults = {
'nth': 4,
'char': '|'
};
for (var property in opts) {
if (opts.hasOwnProperty(property)) {
defaults[property] = opts[property];
}
}
if (defaults.string) {
return haystack = defaults.string.split('').map(function(character, index) {
return (index + 1) % parseInt(defaults.nth) === 0 ? defaults.char : character;
}).join('');
}
}
// 'snippet.log()' is used only in this demonstration, in real life use
// 'console.log()', or print to screen or display in whatever other
// method you prefer.
// calling the function, passing in the supplied 'string'
// property value:
snippet.log( replaceNthWith({
'string': "abcdefoihewfojias"
}) );
// outputs: abc|efo|hew|oji|s
// calling the function with the same string, but to replace
// every second character ( 'nth' : 2 ):
snippet.log( replaceNthWith({
'string': "abcdefoihewfojias",
'nth': 2
}) );
// outputs: a|c|e|o|h|w|o|i|s
// passing in the same string once again, working on every
// third character, and replacing with a caret ('^'):
snippet.log( replaceNthWith({
'string': "abcdefoihewfojias",
'nth': 3,
'char' : '^'
}) );
// outputs: ab^de^oi^ew^oj^as
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
References:
Array.prototype.map().
Array.prototype.join().
for...in loop.
JavaScript Remainder (%) operator.
Object.prototype.hasOwnProperty().
String.prototype.split().
function replaceWith(word,nth, replaceWithCh) {
//match nth position globally
//'\S' is for non-whitespace
let regex = new RegExp("(\\S{" + (nth - 1) + "})\\S", "g");
// '$1' means single group
// after each group position replaceWithCharecter
let _word = word.replace(regex, "$1" + replaceWithCh);
return _word;
}
const str = "abcdefoihewfojias";
const result = replaceWith(str, 3, "X");
console.log(result);

Categories

Resources