Javascript convert string to array with seperate letters and number - javascript

I have a string where I need to strip out the letters and the numbers. There will only be one number in the string.
So for example this string:
"AM12" I would like to split into this:
['A','M',12]
What is the most efficient way to do this? I was able to do it before with dashes in the string separating them (A-M-12) but was asked to remove the dashes.
Here is code I used for with dashes:
let arrUrl = myString.split('-');
Thanks.

You could use /\d+|./. It will match consecutive numbers or individual characters.
const split = str => str.match(/\d+|./g)
console.log(split("AM12"))
console.log(split("Catch22"))

If you need the number portion to be numeric in your resulting array, you could try something like this
let test = 'AM12'
let res = []
let num = ''
test.split('').forEach(e=>isNaN(e)?res.push(e):num+=e)
res.push(parseInt(num))
console.log(res)

You can scan the input string linearly, char by char, and keep track of any running number, also you should pay attention to the negative numbers.
The following snippet handles negative numbers and also multiple numbers in the same input.
function isDigit(char) {
return char >= "0" && char <= "9";
}
function split(input) {
const result = [];
// keep track of the running number if any
let runningNum = 0;
let isNum = false;
let isNegative = false;
for (let i = 0; i < input.length; i++) {
const ch = input[i];
if (isDigit(ch)) {
// check for negative value
if (i > 0 && input[i - 1] === "-") {
isNegative = true;
}
runningNum *= 10;
runningNum += (isNegative ? -1 : 1) * (ch - "0");
isNum = true;
} else {
// push previous running number if any
if (isNum) {
result.push(runningNum);
runningNum = 0; // reset
isNum = false;
isNegative = false;
}
// if current char is a "-" sign and the following char is a digit continue,
// if not then it's a hyphen
const isLastChar = i === input.length - 1;
if (!isLastChar && input[i] === "-" && isDigit(input[i + 1])) {
continue;
}
result.push(ch);
}
}
// in case the number at the end of the input string
if (isNum) {
result.push(runningNum);
}
return result;
}
const inputs = ["AM-12", "AM-12-30", "AM-12B30", "30", "a3b", "ab", "-", "-abc", "a-12-"];
for (let input of inputs) {
console.log(`"${input}": `, split(input));
}

Related

What is the fastest way to count the number of lines in a string in JavaScript?

I'm looking for the most performant way to count the number of lines in a string in JavaScript for a string of any length. I have tested three approaches, but I feel like there may be a faster way that one of you is aware of.
Method 1:
// Split the string on newlines into an array and measure the array length
return string.split(/\r|\r\n|\n/g).length;
Method 2:
// Use match instead of split
return (string.match(/\r|\r\n|\n/g) || '').length + 1;
Method 3:
// Replace all of the newlines with empty space and compare line lengths
return string.length - string.replace(/\r|\r\n|\n/g, '').length + 1;
Find the first occurrence of a possible line break character and count this character:
function countLines(string) {
let count = 1;
let chr;
let i = 0, end = string.length;
for (; i < end; ++i) {
if (string[i] == '\n' || string[i] == '\r') {
count = 2;
chr = string[i];
break;
}
}
for (++i; i < end; ++i) {
if (string[i] == chr) {
++count;
}
}
return count;
}
const linuxString = 'Some\ntext\nwith\nfive\nlines';
const windowsString = 'Some\r\ntext\r\nwith\r\nfive\r\nlines';
const classicMacString = 'Some\rtext\rwith\rfive\rlines';
console.log(countLines(linuxString));
console.log(countLines(windowsString));
console.log(countLines(classicMacString));

Time Complexity of my 2 pointer algorithm

For the given problem below, what would be the time complexity of my solution (below the problem). I think it is not O(n^2), but I am not sure if it is O(n).
Problem: You are given two strings s and t. You can select any substring of string s and rearrange the characters of the selected substring. Determine the minimum length of the substring of s such that string t is a substring of the selected substring.
Signature int minLengthSubstring(String s, String t)
Input s and t are non-empty strings that contain less than 1,000,000 characters each
Output Return the minimum length of the substring of s. If it is not possible, return -1
Example s = "dcbefebce" t = "fd" output = 5
Explanation: Substring "dcbef" can be rearranged to "cfdeb", "cefdb", and so on. String t is a substring of "cfdeb". Thus, the minimum length required is 5.
My code:
function minLengthSubstring(s, t) {
// Write your code here
if(t.length > s.length) return -1;
let letters = new Map();
for(const tc of t) {
letters.set(tc, (letters.get(t) || 0) +1);
}
let min = Infinity;
let start = 0;
let i = 0;
let count = 0;
let map = new Map(letters);
while(i < s.length) {
if(map.has(s[i])) {
if(start === 0 && count === 0) start = i;
count++;
if(map.get(s[i]) === 1) map.delete(s[i])
else map.set(s[i], map.get(s[i]) -1);
if(count === t.length) {
min = Math.min(min, i-start+1);
map = new Map(letters);
count = 0;
start++;
i = start;
}
} else {
i++;
}
}
return min === Infinity ? -1 : min;
}
Thank you.

Generating Numbers while adding zeros infront

I am trying to generate a function that generates sequence of numbers and add 0 accordingly to its front. However, it's not outputting the right numbers:
const generatingNumber = (start, end) => {
let result = [];
let output = '';
for(let num = start; num <= end; num++){
if(num.toString().length === 1){
output = '000' + num.toString();
result.push(parseInt(output));
} else if (num.toString().length === 2){
output = '00' + num.toString();
result.push(parseInt(output));
} else if (num.toString() === 3){
output = '0' + num.toString();
result.push(parseInt(output));
}
result.push(num);
}
return result.join('\n');
};
console.log(generatingNumber(1, 3000));
Any idea what am I missing here why its not adding zeros?
Also is there a more succint way to do this?
You can use padStart method.
The padStart() method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start of the current string.
const generatingNumber = (start, end) => {
let result = [];
let output = '';
for (let num = start; num <= end; num++) {
result.push(num.toString().padStart(4, 0));
}
return result.join('\n');
};
console.log(generatingNumber(1, 10));
Is this something you want
const generatingNumber = (start, end) => {
let result = [];
let output = '';
for (let num = start; num <= end; num++) {
if (num.toString().length === 1) {
output = '000' + num.toString();
result.push(output);
} else if (num.toString().length === 2) {
output = '00' + num.toString();
result.push(output);
} else if (num.toString().length === 3) {
output = '0' + num.toString();
result.push(output);
} else {
result.push(num);
}
}
return result.join('\n');
};
console.log(generatingNumber(1, 3000));
parseInt('0001') will result in 1. parseInt will remove all the 0's before of actual number because 0001 & 1 is same in integer.
So you have to push only string in result.
parseInt() Removes all the leading zeros from the string before parsing it. You can change
output = '0' + num.toString();
result.push(parseInt(output));
to
output = '0' + num.toString();
result.push(output);
and all other similar states where you push to result array.
It will be storing strings but you cant store numbers with leading zeros.
What you want is not to modify the value, but the presentation of the value instead.
There's no numerical difference between "00000000" and "0"; both are still the value 0. So if your value is converted to a number type, you'll not be able to show those leading zeroes.
This is the line where you're converting the digits to a numeric value
result.push(parseInt(output));
If you want to preserve the leading zeroes in your output, do not convert it to number; keep it as a string.
Also, instead of having those manual ifs depending on the length, take a look at the padStart method. It can "fill" those zeroes at the front for however many digits you want, not just 4.
A generic way of doing that without bounds to specific length or range, using Array.from, map, and padStart:
const generatingNumber = (start, end) => {
const range = end - start + 1;
const maxLen = ('' + end).length;
return Array.from({length: range}).map((_, i) =>
(i + start).toString().padStart(maxLen, '0'));
};
console.log(generatingNumber(5, 3000).join('\n'));

How to find a first occurrence of double digit number

So, I am pushing elements into array through prompt until getting 0. After that I am trying to find the first double digit number. For example if the array is [2,3,55,0] my program should return 55.
function findFirstDouble() {
var niz = []
var a = 1;
for (var i = 1; a != 0; i++) {
var unos = parseInt(prompt("Enter number :"))
niz.push(unos)
a = unos
}
alert(niz);
for (var i = 0; i < niz.length; i++) {
if (niz[i] / 10 > 0 && niz[i] / 100 == 0) {
console.log(niz[i]);
break;
}
else {
alert("No double digit numbers!")
break;
}
}
}
findFirstDouble();
Please use built in js function find.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
Here is the solution
// I assume that you already have an array
const niz = [2,3,55,0]
const firstDoubleDigit = niz.find(num => num < 100 && num >= 10)
console.log(firstDoubleDigit)
Here is the answer I think you are looking for.
I omitted the array filling part.
Why would you do any kind of division if you just need to check every number and if the first one matches the criteria then you've got your double digit number hence exit the loop with break or return keyword.
var niz = [1, 2, 55, 13];
for (var i = 0; i < niz.length; i++) {
if (niz[i] > 9 && niz[i] < 100) {
console.log('Pronadeni broj je:', niz[i]);
break;
}
}
You can also convert to string: if (niz[i].toString().length===2){ // your number }
Easy way without math is just to convert it to a string.
const data = [2,3,55,0];
const res = data.findIndex(n=>`${n}`.length===2);
console.log(res > -1 ? "Exists at position " + res : "Doesn't exist");
Mathematically:
const data = [2,111,3,55,0];
const res = data.find(n=>n<100&&n>9);
console.log(res ? "Exists " + res : "Doesn't exist");

Get Number of Decimal Places with Javascript

How would I calculate the number of decimal places (not digits) of a real number with Javascript?
function countDecimals(number) {
}
For example, given 245.395, it should return 3.
Like this:
var val = 37.435345;
var countDecimals = function(value) {
let text = value.toString()
// verify if number 0.000005 is represented as "5e-6"
if (text.indexOf('e-') > -1) {
let [base, trail] = text.split('e-');
let deg = parseInt(trail, 10);
return deg;
}
// count decimals for number in representation like "0.123456"
if (Math.floor(value) !== value) {
return value.toString().split(".")[1].length || 0;
}
return 0;
}
countDecimals(val);
The main idea is to convert a number to string and get the index of "."
var x = 13.251256;
var text = x.toString();
var index = text.indexOf(".");
alert(text.length - index - 1);
Here is a method that does not rely on converting anything to string:
function getDecimalPlaces(x,watchdog)
{
x = Math.abs(x);
watchdog = watchdog || 20;
var i = 0;
while (x % 1 > 0 && i < watchdog)
{
i++;
x = x*10;
}
return i;
}
Note that the count will not go beyond watchdog value (defaults to 20).
I tried some of the solutions in this thread but I have decided to build on them as I encountered some limitations. The version below can handle: string, double and whole integer input, it also ignores any insignificant zeros as was required for my application. Therefore 0.010000 would be counted as 2 decimal places. This is limited to 15 decimal places.
function countDecimals(decimal)
{
var num = parseFloat(decimal); // First convert to number to check if whole
if(Number.isInteger(num) === true)
{
return 0;
}
var text = num.toString(); // Convert back to string and check for "1e-8" numbers
if(text.indexOf('e-') > -1)
{
var [base, trail] = text.split('e-');
var deg = parseInt(trail, 10);
return deg;
}
else
{
var index = text.indexOf(".");
return text.length - index - 1; // Otherwise use simple string function to count
}
}
You can use a simple function that splits on the decimal place (if there is one) and counts the digits after that. Since the decimal place can be represented by '.' or ',' (or maybe some other character), you can test for that and use the appropriate one:
function countPlaces(num) {
var sep = String(23.32).match(/\D/)[0];
var b = String(num).split(sep);
return b[1]? b[1].length : 0;
}
console.log(countPlaces(2.343)); // 3
console.log(countPlaces(2.3)); // 1
console.log(countPlaces(343.0)); // 0
console.log(countPlaces(343)); // 0
Based on Gosha_Fighten's solution, for compatibility with integers:
function countPlaces(num) {
var text = num.toString();
var index = text.indexOf(".");
return index == -1 ? 0 : (text.length - index - 1);
}
based on LePatay's solution, also take care of the Scientific notation (ex: 3.7e-7) and with es6 syntax:
function countDecimals(num) {
let text = num.toString()
if (text.indexOf('e-') > -1) {
let [base, trail] = text.split('e-')
let elen = parseInt(trail, 10)
let idx = base.indexOf(".")
return idx == -1 ? 0 + elen : (base.length - idx - 1) + elen
}
let index = text.indexOf(".")
return index == -1 ? 0 : (text.length - index - 1)
}
var value = 888;
var valueLength = value.toString().length;

Categories

Resources