How can I generate a numeric score for a string, which I can later user to order things alphabetically?
(I'd like to add objectIds to a redis sorted set based on a name property. This needs a numeric score. My list-of-things might be too big to sort all at once, hence wanting to score each item individually)
Words earlier in an alphabetic list should have a lower score, with 'a' = 0.
My naive approach so far; (letter alphabetic position from Replace a letter with its alphabet position )
function alphaScoreString(inputString) {
let score = 0
inputString
.trim()
.toLowerCase()
.split('')
.map((letter, index) => {
const letterNumber = parseInt(letter, 36) - 10
if (letterNumber >= 0) {
score += letterNumber / (index + 1)
}
})
return score * 1000
}
This does not work, as
alphaScoreString('bb')
1500
alphaScoreString('bc')
2000
alphaScoreString('bbz')
9833.333333333334
You can see that 'bbz' has a higher score than 'bc', whereas it should be lower, as 'bbz' would come before 'bc' in an alphabetical list.
You can convert each character to its unicode (and ensure that every character is 4 digits by padding the string. e.g. "H" = 72 but is padded to 0072: Doing a word by word comparison, you can still determine the 'alphabetical order' of each string:
var instring = "Hello World";
var output = "";
for(i=0; i<instring.length;i++){
const newchar = String(instring.charCodeAt(i)).padStart(4, '0');
output = output.concat(newchar)
console.log(output);
}
Answer writen in python.
char_codex = {'a':0.01, 'b':0.02, 'c':0.03, 'd':0.04, 'e':0.05, 'f':0.06,
'g':0.07, 'h':0.08, 'i':0.09, 'j':0.10, 'k':0.11, 'l':0.12,
'm':0.13, 'n':0.14, 'o':0.15, 'p':0.16, 'q':0.17, 'r':0.18,
's':0.19, 't':0.20, 'u':0.21, 'v':0.22, 'w':0.23, 'x':0.24,
'y':0.25, 'z':0.26}
def alphabetic_score(word):
bitwiseshift = '1'
scores = [0.00] * len(word)
for index, letter in enumerate(word.lower()):
if index is 0:
scores[index] = char_codex[letter]
else:
bitwiseshift = bitwiseshift+'00'
scores[index] = char_codex[letter]/int(bitwiseshift)
return sum(scores)
Related
I have an alphanumeric string, so I want to mask all the numbers in this string when the count of digits reaches 10. In this example, the digit count has reached the count of 10 two times irrespective of how many space, special character,s or digits are there
For ex:
string 1:- abc23 56 dfg %#34567fhgh0 1234567890 abc345
Output:- abc** ** dfg %#*****fhgh* ********** abc345
It ignores the characters and mask the number when the digit length reaches 10. I want to do this with regex. How can I do that?
You may use something like this:
if ((s.match(/\d/g) || []).length >= 10) {
s = s.replace(/\d/g, '*');
}
This will count the number of digit matches. If there are 10 or more digits, it replaces each one with a '*' character. If you want to only replace the digits if the string contains at least one set of 10 consecutive digits, see the end of the answer.
Here's a complete example:
var arr = ['abc23 56 dfg %#34567fhgh0 1234567890 abc345', 'abc123def'];
for (var i = 0; i < arr.length; i++) {
let s = arr[i];
if ((s.match(/\d/g) || []).length >= 10) {
s = s.replace(/\d/g, '*');
arr[i] = s;
}
console.log(s);
}
Output:
abc** ** dfg %#*****fhgh* ********** abc***
abc123def
If you want the condition to be for 10 consecutive digits, use the following instead:
if (/\d{10}/g.test(s)) {
s = s.replace(/\d/g, '*');
}
You could split() the string into an array, check the length of the string, if it is over 10, then map the mask character where the number was using splice and its key along with Number and isNan.
var str = 'abc23 56 dfg %#34567fhgh0 1234567890'
var str2 = 'abc345'
var str3 = '%#34567fhg7'
var str4 = '1234567890'
const exchange = (str, cap) => {
// split the string and define array
const arr = str.split('')
// condtional to see if string.length is greater than cap
if (str.length > cap) {
// we have a string longer than cap, loop over the array, exclude
// empty spaces and check if value is a number using isNaN, if it is,
// we splice its value using the key with the mask character x
arr.map((char, k) => char !== ' ' ? Number.isNaN(Number(char)) ? null : arr.splice(k, 1, 'x') : null)
// return the value as a string by joining the array values together
return arr.join('')
} else {
// return the string as its length is not more than cap
return str
}
}
console.log(`${exchange(str, 10)}, length = ${str.length}`)
console.log(`${exchange(str2, 10)}, length = ${str2.length}`)
console.log(`${exchange(str3, 10)}, length = ${str3.length}`)
console.log(`${exchange(str4, 10)}, length = ${str4.length}`)
I have an integer containing various digits, I want to remove 4th digit from an integer. How can I achieve that ?
Example :
let number = 789012345
Here I want to remove 0
Try this :
// Input
let number = 789012345;
// Convert number into a string
let numberStr = number.toString();
// Replace the 0 with empty string
const res = numberStr.replace(numberStr[3], '');
// Convert string into a number.
console.log(Number(res));
Rohìt Jíndal's answer is excellent. I just want to point out another way you could do this with string.replace and capturing groups.
function removeDigit(input, index) {
let exp = new RegExp(`^(\\d{${index}})(\\d)(.+)$`);
return parseInt(input.toString().replace(exp, '$1$3'));
}
let output = removeDigit(789012345, 3);
console.log(output); // 78912345
In this example, I have created a new RegExp object from a template literal in order to inject the index.
The first capturing group contains all digits up to the desired index. The second contains the digit we want to remove and the third contains the remainder of the string.
We then return an integer parsed from the string combination of only the first and third capturing groups.
You can follow this procedure:
Decide if you want to remove digits by index or by value, the following demo will remove by value, which means it will remove all values that match
Convert the number into a string
Convert the string to an array with Array.from
Use Array#filter to remove target digit(s)
Use Array#join to create a string
Use + to convert to string back into a numeric value
const n = 789012345;
const m = +Array.from( n.toString() ).filter(num => +num !== 0).join("");
console.log( m );
let numberWithoutADigit = removeIthDigitFromNumber(789012345, 4);
function removeIthDigitFromNumber(n, i){
//convert the number n to string as an array of char
let o = (n + '').split('');
//remove the item at the index i (0 based) from the array
o.splice(i, 1);
//rebuilds the string from the array of char and parse the string to return a number
let number = parseInt(o.join(''));
return number;
}
let number = 789012345
let i = 3 // index 3, 4th digit in number
let arr = number.toString().split("").filter((value, index) => index!==i);
// ['7', '8', '9', '1', '2', '3', '4', '5']
let new_number = parseInt(arr.join(""))
// 78912345
console.log(new_number)
let x = 789012345
var nums = [];
let i = 0, temp = 0;
while(x > 1){
nums[i++] = (x % 10);
x = (x - (x % 10)) / 10;
}
var cnt = 0;
for(--i; i >= 0; i--){
if (cnt++ == 3) continue;
temp = temp * 10 + nums[i];
}
I have a string that I would like to break down into an array.
Each index needs to have a max letter, say 15 characters. Each point needs to be at a words end, with no overlap of the maximum characters (IE would stop at 28 chars before heading into next word).
I've been able to do similar things using regex in the past, but I'm trying to make this work with an online platform that does not like regex.
Example string:
Hi this is a sample string that I would like to break down into an array!
Desired result # 15 char max:
Hi this is a
sample string
that I would
like to break
down into an
array!
Considering there's no word bigger then max limit
function splitString (n,str){
let arr = str?.split(' ');
let result=[]
let subStr=arr[0]
for(let i = 1; i < arr.length; i++){
let word = arr[i]
if(subStr.length + word.length + 1 <= n){
subStr = subStr + ' ' + word
}
else{
result.push(subStr);
subStr = word
}
}
if(subStr.length){result.push(subStr)}
return result
}
console.log(splitString(15,'Hi this is a sample string that I would like to break down into an array!'))
I want to create a javascript function to flip 1's to 0's in a natural number and I'm out of Ideas to achieve this,
Actually, I had a couple of URL's, and I replaced all 0's from a query parameter with 1's and now I no longer know the original parameter value, because there were few 1's in the original parameter value and now both are mixed, so basically I screwed myself,
The only solution for me is to try flipping each 1 to 0 and then 0's to 1's and test each number as the parameter.
This is the parameter value (after replacing 0's with 1's)
11422971
using above input I want to generate numbers as follows and test each of these
11422970
10422971
10422970
01422971
As you can see only 1's and 0's are changing, the change according to binary,
Each position in your string can be one of n characters:
A "0" can be either "0" or "1"
A "1" can be either "0" or "1"
Any other character c can only be c
We can store this in an array of arrays:
"11422971" -> [ ["0", "1"], ["0, "1"], ["4"], ... ]
To transform your string to this format, you can do a split and map:
const chars = "11422971"
.split("")
.map(c => c === "1" || c === "0" ? ["1", "0"] : [ c ]);
Once you got this format, the remaining logic is to create all possible combinations from this array. There are many ways to do so (search for "array combinations" or "permutations"). I've chosen to show a recursive pattern:
const chars = "11422971"
.split("")
.map(c =>
c === "1" || c === "0"
? ["1", "0"]
: [ c ]
);
const perms = ([ xs, ...others ], s = "", ps = []) =>
xs
? ps.concat(...xs.map(x => perms(others, s + x, ps)))
: ps.concat(s);
console.log(perms(chars));
you can do it with a number like a string, and after parse it, something like that
var number= "12551";
number= number.replace("1","0");
The result of number will be "02550"
after that parse number to int
This will generate all permutations.
const generatePermutations = (number) => {
let digits = number.split('');
// find out which digits can be flipped
let digitPositions = digits.reduce((acc, val, i) => {
if (val === '0' || val === '1') acc.push(i);
return acc;
}, []);
// we're going to be taking things in reverse order
digitPositions.reverse();
// how many digits can we flip
let noBits = digitPositions.length;
// number of permutations is 2^noBits i.e. 3 digits means 2^3 = 8 permutations.
let combinations = Math.pow(2, digitPositions.length);
let permutations = [];
// for each permutation
for (var p = 0; p < combinations; p++) {
// take a copy of digits for this permutation
permutations[p] = digits.slice();
// set each of the flippable bits according to the bit positions for this permutation
// i = 3 = 011 in binary
for (var i = 0; i < noBits; i++) {
permutations[p][digitPositions[i]] = '' + ((p >> i) & 1);
}
permutations[p] = permutations[p].join('');
}
return permutations;
};
console.log(generatePermutations('11422970'));
In case your looking for a recursive approach:
function recursive(acc, first, ...rest) {
if(!first) return acc;
if(first == '0' || first == '1') {
var acc0 = acc.map(x => x + '0');
var acc1 = acc.map(x => x + '1');
return recursive([].concat(acc0, acc1), ...rest);
} else {
return recursive(acc.map(x => x + first), ...rest);
}
}
recursive([''], ...'11422971')
// output ["00422970", "10422970", "01422970", "11422970", "00422971", "10422971", "01422971", "11422971"]
This just counts in binary and fills out a template for each value.
function getPossibleValues(str) {
function getResult(n) {
let nIndex = 0;
const strValue = n.toString(2).padStart(nDigits, '0');
return str.replace(rxMatch, () => strValue.charAt(nIndex++));
}
const rxMatch = /[01]/g;
const nDigits = str.length - str.replace(rxMatch, '').length;
const nMax = Math.pow(2, nDigits);
const arrResult = [];
for(let n = 0; n<nMax; n++) {
arrResult.push(getResult(n));
}
return arrResult;
}
console.log(getPossibleValues('11422970'));
Thank you all to respond, you saved my life, btw the approach I used was,
0- convert the number into a string. (so we can perform string operations like split())
1- count the number of 1's in the string (let's say the string is "11422971", so we get three 1's, I used split('1')-1 to count)
2- generate binary of three-digit length,(ie from 000 to 111). three came from step 1.
2- break down the string to single chars, (we'll get
array=['1','1','4','2','2','9','7','1'] )
3- take the first binary number (ie b=0b000)
4- replace first 1 from the character array with the first binary digit of b (ie replace 1 with 0), similarly replace second 1 with the second binary digit of b and so on.
5- we'll get the first combination (ie "00422970")
5- repeat step 3 and 4 for all binary numbers we generated in step 2.
I want to convert a number to its corresponding alphabet letter. For example:
1 = A
2 = B
3 = C
Can this be done in javascript without manually creating the array?
In php there is a range() function that creates the array automatically. Anything similar in javascript?
Yes, with Number#toString(36) and an adjustment.
var value = 10;
document.write((value + 9).toString(36).toUpperCase());
You can simply do this without arrays using String.fromCharCode(code) function as letters have consecutive codes. For example: String.fromCharCode(1+64) gives you 'A', String.fromCharCode(2+64) gives you 'B', and so on.
Snippet below turns the characters in the alphabet to work like numerical system
1 = A
2 = B
...
26 = Z
27 = AA
28 = AB
...
78 = BZ
79 = CA
80 = CB
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var result = ""
function printToLetter(number){
var charIndex = number % alphabet.length
var quotient = number/alphabet.length
if(charIndex-1 == -1){
charIndex = alphabet.length
quotient--;
}
result = alphabet.charAt(charIndex-1) + result;
if(quotient>=1){
printToLetter(parseInt(quotient));
}else{
console.log(result)
result = ""
}
}
I created this function to save characters when printing but had to scrap it since I don't want to handle improper words that may eventually form
Just increment letterIndex from 0 (A) to 25 (Z)
const letterIndex = 0
const letter = String.fromCharCode(letterIndex + 'A'.charCodeAt(0))
console.log(letter)
UPDATE (5/2/22): After I needed this code in a second project, I decided to enhance the below answer and turn it into a ready to use NPM library called alphanumeric-encoder. If you don't want to build your own solution to this problem, go check out the library!
I built the following solution as an enhancement to #esantos's answer.
The first function defines a valid lookup encoding dictionary. Here, I used all 26 letters of the English alphabet, but the following will work just as well: "ABCDEFG", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "GFEDCBA". Using one of these dictionaries will result in converting your base 10 number into a base dictionary.length number with appropriately encoded digits. The only restriction is that each of the characters in the dictionary must be unique.
function getDictionary() {
return validateDictionary("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
function validateDictionary(dictionary) {
for (let i = 0; i < dictionary.length; i++) {
if(dictionary.indexOf(dictionary[i]) !== dictionary.lastIndexOf(dictionary[i])) {
console.log('Error: The dictionary in use has at least one repeating symbol:', dictionary[i])
return undefined
}
}
return dictionary
}
}
We can now use this dictionary to encode our base 10 number.
function numberToEncodedLetter(number) {
//Takes any number and converts it into a base (dictionary length) letter combo. 0 corresponds to an empty string.
//It converts any numerical entry into a positive integer.
if (isNaN(number)) {return undefined}
number = Math.abs(Math.floor(number))
const dictionary = getDictionary()
let index = number % dictionary.length
let quotient = number / dictionary.length
let result
if (number <= dictionary.length) {return numToLetter(number)} //Number is within single digit bounds of our encoding letter alphabet
if (quotient >= 1) {
//This number was bigger than our dictionary, recursively perform this function until we're done
if (index === 0) {quotient--} //Accounts for the edge case of the last letter in the dictionary string
result = numberToEncodedLetter(quotient)
}
if (index === 0) {index = dictionary.length} //Accounts for the edge case of the final letter; avoids getting an empty string
return result + numToLetter(index)
function numToLetter(number) {
//Takes a letter between 0 and max letter length and returns the corresponding letter
if (number > dictionary.length || number < 0) {return undefined}
if (number === 0) {
return ''
} else {
return dictionary.slice(number - 1, number)
}
}
}
An encoded set of letters is great, but it's kind of useless to computers if I can't convert it back to a base 10 number.
function encodedLetterToNumber(encoded) {
//Takes any number encoded with the provided encode dictionary
const dictionary = getDictionary()
let result = 0
let index = 0
for (let i = 1; i <= encoded.length; i++) {
index = dictionary.search(encoded.slice(i - 1, i)) + 1
if (index === 0) {return undefined} //Attempted to find a letter that wasn't encoded in the dictionary
result = result + index * Math.pow(dictionary.length, (encoded.length - i))
}
return result
}
Now to test it out:
console.log(numberToEncodedLetter(4)) //D
console.log(numberToEncodedLetter(52)) //AZ
console.log(encodedLetterToNumber("BZ")) //78
console.log(encodedLetterToNumber("AAC")) //705
UPDATE
You can also use this function to take that short name format you have and return it to an index-based format.
function shortNameToIndex(shortName) {
//Takes the short name (e.g. F6, AA47) and converts to base indecies ({6, 6}, {27, 47})
if (shortName.length < 2) {return undefined} //Must be at least one letter and one number
if (!isNaN(shortName.slice(0, 1))) {return undefined} //If first character isn't a letter, it's incorrectly formatted
let letterPart = ''
let numberPart= ''
let splitComplete = false
let index = 1
do {
const character = shortName.slice(index - 1, index)
if (!isNaN(character)) {splitComplete = true}
if (splitComplete && isNaN(character)) {
//More letters existed after the numbers. Invalid formatting.
return undefined
} else if (splitComplete && !isNaN(character)) {
//Number part
numberPart = numberPart.concat(character)
} else {
//Letter part
letterPart = letterPart.concat(character)
}
index++
} while (index <= shortName.length)
numberPart = parseInt(numberPart)
letterPart = encodedLetterToNumber(letterPart)
return {xIndex: numberPart, yIndex: letterPart}
}
this can help you
static readonly string[] Columns_Lettre = new[] { "A", "B", "C"};
public static string IndexToColumn(int index)
{
if (index <= 0)
throw new IndexOutOfRangeException("index must be a positive number");
if (index < 4)
return Columns_Lettre[index - 1];
else
return index.ToString();
}