How to search multiple same values and look if it meets the conditions without regex? Suppose that I have this string ***6**5****8*9***2
What I need to do is to check if the string has at least three times *** altogether and then if the number before and after the *** sums 11. In the example given, these conditions are met because: First, the string has three *** altogether, and then 9 + 2 is 11.
I have solved this problem using regex, match, and replace, but how I can do it without applying to those solutions.
I have tried to do this without regex but it did not work because indexOf is only giving me one result:
string = "***6**5****8*9***2";
for (var i = 0; i < string.length; i++) {
let where = (string.indexOf("***"));
let a = parseInt(string.charAt(where - 1));
let b = parseInt(string.charAt(where + 3));
if (a + b == 11){
isTrue = true;
}
}
You could split the string by stars amd keep the starts in the array then check if the value starts with a star, check the length and the left and right element for sum.
var string = "***6**5****8*9***2",
parts = string.split(/(\*+)/),
result = parts.some((s, i, { [i - 1]: l, [i + 1]: r }) =>
s[0] === '*' && s.length >= 3 && +l + +r === 11
);
console.log(result);
console.log(parts);
I tried to create a solution based off of your existing code:
string = "***6**5****8*9***2***4";
let where = 0;
// Skip leading *
while (where < string.length && '*' == string.charAt(where)) {
where += 1;
}
while (true) {
// Find three stars based on previous result
where = string.indexOf("***", where);
// No more triples
if (where == -1) break;
// Convert to digit - will be NaN if not a digit
let a = parseInt(string.charAt(where - 1));
// Find trailing digit
let j = where + 1;
// Skip to next non * char
while (j < string.length && '*' == string.charAt(j)) {
j += 1;
}
// No matches - quit
if (j == string.length) break;
// Parse digit
let b = parseInt(string.charAt(j));
// Do the math
if (!isNaN(a) && !isNaN(b)){
console.log(`${a} + ${b} = ${a+b}`);
}
where = j;
}
I wrote a simple Parser.I hope it can help you
string = "***6**5****8*9***2";
class Parser {
static parse(string) {
var lexer = new Lexer(string);
var token = lexer.getToken();
var prevNumberToken = null ;
while (token.type !== TOKEN_TYPE_END) {
if(token.type === TOKEN_TYPE_NUMBER){
if(prevNumberToken && prevNumberToken.value + token.value === 11 ) {
return true;
}
prevNumberToken = token ;
} else if(token.type !== TOKEN_TYPE_THREESTARS){
prevNumberToken = null ;
}
token = lexer.getToken();
}
return false;
}
}
class Lexer {
constructor(string) {
this._string = string;
this._index = -1;
this._len = string.length;
}
getToken() {
if (this._index < 0) {
this._index = 0;
return new Token(TOKEN_TYPE_START, '', -1);
}
if (this._index >= this._len) {
return new Token(TOKEN_TYPE_END, '', this._len);
}
if (this._string[this._index] === "*") {
return this._getStarToken()
} else {
return this._getNumberToken();
}
}
_getStarToken() {
var stars = "";
var i = this._index;
while (this._index < this._len && this._string[this._index] === "*") {
stars += "*";
this._index++;
}
if (stars.length === 3) {
return new Token(TOKEN_TYPE_THREESTARS, stars, i)
}
return new Token(TOKEN_TYPE_STARS, stars, i)
}
_getNumberToken() {
var numbers = "";
var i = this._index;
while (this._index < this._len && this._string[this._index] !== "*") {
if (this._string[this._index] >= "0" && this._string[this._index] <= "90") {
numbers += this._string[this._index];
this._index++;
} else {
throw new Error("invalid character")
}
}
return new Token(TOKEN_TYPE_NUMBER, parseInt(numbers), i);
}
}
class Token {
constructor(type, value, index) {
this._type = type
this._index = index
this._value = value
}
get type() { return this._type }
get index() { return this._index }
get value() { return this._value }
}
const TOKEN_TYPE_START = 1;
const TOKEN_TYPE_NUMBER = 2;
const TOKEN_TYPE_THREESTARS = 4;
const TOKEN_TYPE_STARS = 8;
const TOKEN_TYPE_END = 16;
console.log(Parser.parse(string));
i have one phone number text-field.Now,i want to apply regex through java-script. for that i used below code.but it is not accept 10 digit.would any told me that what is wrong with below code.
java script code:-
function val(value) {
var p = phonevalue1
p = p.replace(/[^\d]*/gi, "")
if (p.length <= 5) {
value.value = p;
}
else if (p.length > 5 && p.length < 9) {
var a = p.substring(0, 5);
var b = p.substring(5, p.length);
var c = a + "-" + b;
value.value = c;
}
else if (p.length >= 9) {
var len = p.length;
var a = p.substring(0, 5);
var b = p.substring(5, len);
var c = a + "-" + b;
value.value = c.substring(0, 10);
}
}
From what I can tell you want the following
5 or less digits just add digits to value property of value object
6 - 8 digits add hyphen after fifth digit as in 12345-678
9 digits or greater 12345-6789
NOTES:
value.value means value is an {};
phonevalue1 is undefined in the function, so I will assume it is defined in the parent scope and is some string of numbers.
The code you have provided can be simplified a bit. I will make some adjustments and you'll have to adjust how your code block handles the function. K?
function val(value) {
var p = phonevalue1
p = p.replace(/[^\d]*/gi, "")
if (p.length <= 5) {
value.value = p;
}
else if (p.length > 5 && p.length < 9) {
var a = p.substring(0, 5);
var b = p.substring(5, p.length);
var c = a + "-" + b;
value.value = c;
}
else if (p.length >= 9) {
var len = p.length;
var a = p.substring(0, 5);
var b = p.substring(5, len);
var c = a + "-" + b;
value.value = c.substring(0, 10);
}
}
Change to this...
NOTE: Where value is your object as you stated,
var value = {};
var phonevalue1 = "12345";
var phonevalue2 = "12345678";
var phonevalue3 = "1234567890";
value.value = phonevalue1.replace(/(^\d{5})/, "$1-").replace(/-$/, '');
=> { value: "12345" };
value.value = phonevalue2.replace(/(^\d{5})/, "$1-").replace(/-$/, '');
=> { value: "12345-678" };
value.value = phonevalue3.replace(/(^\d{5})/, "$1-").replace(/-$/, '');
=> { value: "12345-67890" };
If you want to use a function as you have, I will try to make the same thing work, but the way your code is structured is not recommended as it is unnecessarily long and confusing.
function addHyphen( numString ){
return numString.replace(/(^\d{5})/, "$1-").replace(/-$/, '');
}
value.value = addHyphen( phonevalue1 );
Hope this helps...
I need to clean characters encoded in UTF-32 from string in JS, like "💣".
I tried to use code:
str.replace(/[^\u0000-\uFFFF]/gi, '')
But it isn't work.
For clean message I used
function fixedCharCodeAt(str, idx) {
var code = str.charCodeAt(idx);
if (0xD800 <= code && code <= 0xDBFF) {
// Upper auxiliary char
var hi = code;
var low = str.charCodeAt(idx+1);
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}
if (0xDC00 <= code && code <= 0xDFFF) {
// Lower auxiliary symbol
var hi = str.charCodeAt(idx-1);
var low = code;
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}
return code;
}
and
function cleaningMsgFromBreakingSymb(message_old) {
var new_message = "";
for (var i = 0, len = message_old.length; i < len; i++) {
if (fixedCharCodeAt(message_old, i) < 65535){
new_message += message_old[i];
};
};
return new_message;
}
I am looking on performance improvement of the script below. I am pretty sure it can be substantially modified, I did it as it was first thing that came to my head and it is only for demonstration purposes on what I am looking for.
function pad(nn, width, z) {
z = z || '0';
nn = nn + '';
return nn.length >= width ? nn : new Array(width - nn.length + 1).join(z) + nn;
}
var makeIntoBinary = function(ii, length) {
return pad(ii.toString(2), length);
}
var makeIntoTrueFalse = function(binary) {
var str = '';
for (iii = 0; iii < binary.length; iii++) {
if (binary[iii] == '0') {
str += ' false';
} else {
str += ' true';
}
};
console.log(str + ' ' + binary);
}
var runner = function(n) {
var iter = Math.pow(2, n);
for (i = 0; i < iter; i++) {
makeIntoTrueFalse(makeIntoBinary(i, n));
}
}
What I am looking for is to generate sets of words for all possible combinations which is essentially doing the binary above. (runner(2); would produce false false, false true, true false, true true) I am looking for lightning fast algorithm that gets me to this point.
Try manipulating bits directly, without extraneous string conversions.
function combinations(n) {
var r = [];
for(var i = 0; i < (1 << n); i++) {
var c = [];
for(var j = 0; j < n; j++) {
c.push(i & (1 << j) ? 'true' : 'false');
}
r.push(c.join(' '));
}
return r;
}
r = combinations(prompt('size?'));
document.write(JSON.stringify(r));
Just for the record, this is probably slower, but way nicer:
Number.prototype.times = function(fn) {
var r = [];
for(var i = 0; i < this; i++)
r.push(fn(i));
return r;
}
function combinations(n) {
return (1 << n).times(function(i) {
return n.times(function(j) {
return Boolean(i & 1 << j);
});
});
}
In my grid the column headers are named A,B,C...,AA,AB,AC,...etc like an excel spreadsheet. How can I convert the string to number like: A => 1, B => 2, AA => 27
Try:
var foo = function(val) {
var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', i, j, result = 0;
for (i = 0, j = val.length - 1; i < val.length; i += 1, j -= 1) {
result += Math.pow(base.length, j) * (base.indexOf(val[i]) + 1);
}
return result;
};
console.log(['A', 'AA', 'AB', 'ZZ'].map(foo)); // [1, 27, 28, 702]
solution 1: best performance and browser compatibility
// convert A to 1, Z to 26, AA to 27
function lettersToNumber(letters){
var chrs = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ', mode = chrs.length - 1, number = 0;
for(var p = 0; p < letters.length; p++){
number = number * mode + chrs.indexOf(letters[p]);
}
return number;
}
solution 2: best performance and compatibility and shorter code (Recommended)
// convert A to 1, Z to 26, AA to 27
function lettersToNumber(letters){
for(var p = 0, n = 0; p < letters.length; p++){
n = letters[p].charCodeAt() - 64 + n * 26;
}
return n;
}
solution 3: short code (es6 arrow function)
// convert A to 1, Z to 26, AA to 27
function lettersToNumber(letters){
return letters.split('').reduce((r, a) => r * 26 + parseInt(a, 36) - 9, 0);
}
test:
['A', 'Z', 'AA', 'AB', 'ZZ','BKTXHSOGHKKE'].map(lettersToNumber);
// [1, 26, 27, 28, 702, 9007199254740991]
lettersToNumber('AAA'); //703
Here's a quick example of the code you should implement.
This will work with any given number of letters.
function letterToNumbers(string) {
string = string.toUpperCase();
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', sum = 0, i;
for (i = 0; i < string.length; i++) {
sum += Math.pow(letters.length, i) * (letters.indexOf(string.substr(((i + 1) * -1), 1)) + 1);
}
return sum;
}
i just wrote a junk yard f##$ snippet... need to be optimized.. :)
charToNum = function(alpha) {
var index = 0
for(var i = 0, j = 1; i < j; i++, j++) {
if(alpha == numToChar(i)) {
index = i;
j = i;
}
}
console.log(index);
}
numToChar = function(number) {
var numeric = (number - 1) % 26;
var letter = chr(65 + numeric);
var number2 = parseInt((number - 1) / 26);
if (number2 > 0) {
return numToChar(number2) + letter;
} else {
return letter;
}
}
chr = function (codePt) {
if (codePt > 0xFFFF) {
codePt -= 0x10000;
return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
}
return String.fromCharCode(codePt);
}
charToNum('A') => returns 1 and charToNum('AA') => returns 27;
// Given Column to Number
function colToNumber(str) {
let num = 0
let i = 0
while (i < str.length) {
num = str[i].charCodeAt(0) - 64 + num * 26;
i++;
}
return num;
}
//Given Number to Column name
function numberToCol(num) {
let str = '', q, r;
while (num > 0) {
q = (num-1) / 26;
r = (num-1) % 26
num = Math.floor(q)
str = String.fromCharCode(65 + r) + str;
}
return str;
}
I rewrote Yoshi's answer in a more verbose form that explains better how it works and is easier to port to other languages:
var foo = function(val) {
var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var baseNumber = base.length;
var runningTotal = 0;
var characterIndex = 0;
var indexExponent = val.length - 1;
while( characterIndex < val.length ){
var digit = val[characterIndex];
var digitValue = base.indexOf(digit) + 1;
runningTotal += Math.pow(baseNumber, indexExponent) * digitValue;
characterIndex += 1
indexExponent -= 1
}
return runningTotal;
};
console.log(['A', 'AA', 'AB', 'ZZ'].map(foo)); // [1, 27, 28, 702]
Public Function ColLet2Num(Letras As String)
'RALONSO MAYO 2017
'A-> 1
'OQ ->407
'XFD->16384
Dim UnChar As String
Dim NAsc As Long
Dim F As Long
Dim Acum As Long
Dim Indice As Long
Letras = UCase(Letras)
Acum = 0
Indice = 0
For F = Len(Letras) - 1 To 0 Step -1
UnChar = Mid(Letras, F + 1, 1)
NAsc = Asc(UnChar) - 64
Acum = Acum + (NAsc * (26 ^ Indice))
Indice = Indice + 1
Next
If Acum > 16384 Then
MsgBox "La celda máxima es la XFD->16384", vbCritical
End If
ColLet2Num = Acum
End Function
const getColumnName = (columnNumber) => {
let columnName = "";
const alphabets = "abcdefghijklmnopqrstuvwxyz".toUpperCase();
while (columnNumber > 0) {
const rem = columnNumber % 26;
if (rem === 0) {
columnName += "Z";
columnNumber = columnNumber / 26 - 1;
} else {
columnName += alphabets[rem - 1];
columnNumber = Math.floor(columnNumber / 26);
}
}
return columnName.split("").reverse().join("");
};
console.log(getColumnName(27));
A good readability and performance example:
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// create dict to O(1) access to letter number
const dict = Object.fromEntries(letters.split('').map((it, index) => [it, index + 1]));
function toNumber(col) {
return col
.toUpperCase()
.split('')
.reduce((acc, letter, index) => acc + Math.pow(letters.length, col.length - (index + 1)) * dict[letter], 0);
}
Highly inspired by the different solutions put forth on this page
//fixed the one taken from here
function colToNumber(str: string): number {
var num = 0
for (var i = 0; i < str.length; i++) {
const current_letter = str.charCodeAt(i) - 64
const current_char = str[i]
if (i == str.length - 1) {
num += current_letter
} else {
var current = current_letter * Math.pow(26, str.length - i - 1)
num += current
}
}
return num;
}
//Given Number to Column name (taken from here)
function numberToCol(num: number) {
var str = '', q: number, r: number;
while (num > 0) {
q = (num - 1) / 26;
r = (num - 1) % 26
num = Math.floor(q)
str = String.fromCharCode(65 + r) + str;
}
return str;
}
function test_both() {
const dic = new Map<number, string>()
dic.set(1,"A")
dic.set(10,"J")
dic.set(13,"M")
dic.set(33,"AG")
dic.set(63,"BK")
dic.set(66,"BN")
dic.set(206,"GX")
dic.set(502,"SH")
dic.set(1003,"ALO")
dic.set(100,"CV")
dic.set(10111,"NXW")
dic.set(10001,"NTQ")
dic.set(9002,"MHF")
dic.set(5002,"GJJ")
dic.set(3002,"DKL")
dic.set(16384,"XFD")
for (var key of dic.keys()) {
const expected_a1 = dic.get(key) || ""
//console.log(`${ key }, ${ expected_a1 } `)
var actual = numberToCol(key)
var actual_num = colToNumber(expected_a1)
if (actual.localeCompare(expected_a1) != 0) {
console.error(`key = ${key} == expected=${expected_a1} actual = ${actual} `)
}
if (actual_num != key) {
console.error(`expected = ${expected_a1} key = ${key} == actual = ${actual_num} `)
}
}
}