Array not sorting correctly in javascript - javascript

I have a Javascript array of strings that I'm sorting using the compareFunction. For the most part, it's sorting correctly:
JS
array = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5", "E10N8", "E10N6", "E10N7"];
function sortStrings(a, b){
if(a < b){
return -1;
}
if(a > b){
return 1;
}
return 0;
}
array.sort(sortStrings);
for(var i = 0; i < array.length; i++){
$(".table_body").append("<div class='table_row'><p>" +array[i] +"</p></div>");
}
The issue I'm having is the sort function is putting the "E10N10" item between"E10N1" and "E10N2" items. So it looks like this:
I understand that sorting strings is done alphabetically, but wouldn't the "E10N10" string still be processed as later than "E10N9"? How do I fix it to have this particular string come last in the array after it's sorted?

You can modify your custom sorting function to handle this. For example, if all of your strings start with 4 characters that you don't care about when sorting, just do this:
function sortStrings(a, b){
a = parseInt(a.substr(4));
b = parseInt(b.substr(4));
if(a < b){
return -1;
}
if(a > b){
return 1;
}
return 0;
}

In alphabetical sort, it just looks at the characters sequentially so "E10N1" would be before "E10N9", even though there is another character after the "E10N1". Just like "abcd" comes before "abd".
If you really want the type of sort you're asking for, it is going to take a much more complicated custom sort algorithm that actually parses the numeric parts of the tag to do actual numeric comparisons (not alphabetic sorts) on them.
Here's is a sorting scheme that sorts based on the trailing digits:
var array = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5", "E10N8", "E10N6", "E10N7"];
var regex = /\d+$/;
function getLastNum(str) {
var m = str.match(regex);
if (m) {
return parseInt(m[0], 10);
} else {
return -1;
}
}
array.sort(function(a, b) {
return getLastNum(a) - getLastNum(b);
});
document.write(JSON.stringify(array));
You can obviously make this as complicated or rich as desired. For example, if you want to identify all numeric sequences in the number and turn each of them into actual numbers, you can do that too. You did not specify how involved this needs to be so I showed the smallest work required to make your specific sequence work (by sorting just by the trailing digits).
For a discussion of several different general purpose algorithms for handling mixed alpha-numeric sorts where the digits can occur anywhere in the string and can occur in multiple places, you can see this article: Sorting for Humans: Natural Sort Order. One particular implementation in Javascript can be found here.
The general idea behind the generic algorithm is as follows:
Get the next character of each string
If not both digits, then compare the characters directly and return the result
If both digits, then collect sequence of digits in both strings
Longest sequence of consecutive digits is higher
While accumulating sequential digits, keep track of which sequence
has the first non-equal digit that is higher than the other
If sequences were the same length, then the previous collected value
of which sequence had the first different higher number determines
which sequence comes first
If sequence of digits or single character were equal, go to next character
and start the above process over
One advantage of this generic algorithm is that it does not actually convert the numeric sequences of digits to a number so it will work on sequences of numbers of arbitrary length without running into limitations on how many digits a number can be in Javascript.
Depending upon your desired algorithm, you may or may not want to ignore whitespace preceding digits and you may or may not want to account for plus or minus signs in front of numbers. And, you may want to use a language aware comparison rather than a strict ascii code comparison. There are lots of factors to consider for any particular use.
Here is a general purpose algorithm that I wrote from scratch:
var array = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5",
"E10N8", "E10N6", "E10N7", "C10N1", "D10N3", "E11N10", "E09N2", "E999N4",
"E10000N9", "g10N6", "z10N6", "q10N6", "R10N6", "E001N1", "E00N1",
"E0000N1", "zN1", "zN000", "zN00", "000", "00", "0001", "0002", "A00",
"A", "0A"];
// return negative value if a < b
// return 0 if a === b
// return positive value if a > b
//
// Rules:
// - Sort characters before numbers
// - Ignore leading zeroes on digits
// - Ignore plus/minus signs in front of digits
// - For sequences of zeroes the shorter sequence is first
//
function alphaNumCompare(a, b) {
var aIndex = 0,
bIndex = 0,
aChar, bChar, result;
function isDigit(ch) {
return ch >= "0" && ch <= "9";
}
function compareNums() {
// aChar, bChar contain first digit
// get rest of consecutive digits and compare
// returns negative, 0 or positive
// as side affect, advances aIndex and bIndex to next non-numeric
var aZeroLen = 0,
bZeroLen = 0,
aNumStr = "",
bNumStr = "";
// collect consecutive digits from a and b
// ignore any leading zeroes
if (aChar === "0") {
++aZeroLen;
} else {
aNumStr = aChar;
}
if (bChar === "0") {
++bZeroLen;
} else {
bNumStr = bChar;
}
while (aIndex < a.length) {
aChar = a.charAt(aIndex);
if (!isDigit(aChar)) {
break;
}
++aIndex;
// don't add leading zeroes and keep a count of leading zeroes
if (aChar === "0" && aNumStr === "") {
++aZeroLen;
} else {
aNumStr += aChar;
}
}
while (bIndex < b.length) {
bChar = b.charAt(bIndex);
if (!isDigit(bChar)) {
break;
}
++bIndex;
// don't add leading zeroes and keep a count of leading zeroes
if (bChar === "0" && bNumStr === "") {
++bZeroLen;
} else {
bNumStr += bChar;
}
}
// we now have a series of consecutive digits in aNumStr and bNumStr
if (aNumStr.length === bNumStr.length) {
// check for nothing but leading zeroes in both
if (aNumStr.length === 0) {
return aZeroLen - bZeroLen;
}
if (aNumStr === bNumStr) {
return 0;
} else {
return aNumStr < bNumStr ? -1 : 1;
}
} else {
// lengths are not equal, then shorter string comes first
return aNumStr.length - bNumStr.length;
}
}
// loop while both strings have characters left
while (aIndex < a.length && bIndex < b.length) {
aChar = a.charAt(aIndex++);
bChar = b.charAt(bIndex++);
if (isDigit(aChar) && isDigit(bChar)) {
result = compareNums();
if (result !== 0) {
return result;
}
} else {
// not both numeric, just compare the characters themselves
result = aChar.localeCompare(bChar);
if (result !== 0) {
return result;
}
}
}
// shorter one is first
return (a.length - aIndex) - (b.length - bIndex);
}
array.sort(alphaNumCompare);
document.write(JSON.stringify(array).replace(/,/g, ", "));
The logic for this is as follows:
Implement a custom sort function for the Array sort() function.
Get next character in the string
If both are digits, then accumulate whatever sequence of consecutive digits there are.
Trim leading zeroes from the sequence of zeroes
If both sequences are only a sequence of zeroes, then the shorter one is less
The shorter sequence of numbers is less than the longer one
If both sequences of numbers are the same length, then you can just do a straight string compare on them to get the result
If both characters are not digits, then just compare them as a string
If strings have compared equal up to the point where one ends, then the shorter one is less

I suggest to use a kind of sort pattern for this special purpopse.
var data = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5", "E10N8", "E10N6", "E10N7"],
result = data.map(function (el, i) {
var a = /(\D*)(\d*)(\D*)(\d*)/i.exec(el);
a.shift();
return { index: i, value: a };
}).sort(function (a, b) {
var i = 0, r = 0;
while (r === 0 && i < a.value.length && i < b.value.length) {
r = i % 2 ? +a.value[i] - +b.value[i] : a.value[i].localeCompare(b.value[i]);
i++;
}
return r;
}).map(function (el) {
return data[el.index];
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

You could use a regex to capture the digits at the end of each element and sort on those instead:
function sortStrings(a, b) {
var regex = /E10N([\d]+)/;
var apost = +a.match(regex)[1];
var bpost = +b.match(regex)[1];
if (apost < bpost) return -1;
if (apost > bpost) return 1;
return 0;
}
DEMO

In ASCII order 1 is less than 9 so "E10N10" is less than "E10N9". To get result you want, you need sorts the numbers in value order, while sorting the non-numbers in ASCII order. You can use this Alphanum Algorithm:
http://www.davekoelle.com/alphanum.html

Related

Convert a string to a big integer in Javascript?

I am trying to convert a string to a big integer to perform some arithmetic calculations. However, when I try this:
Number("9007199254740993")
...I am getting this unexpected result:
9007199254740992
I suspect that this is probably because of the limit on the size of integers that Number is capable of working with.
Basically, I want to check if two strings are consecutive numbers or not. Since Number is not returning the correct value, I am getting the incorrect difference for "9007199254740993" and "9007199254740992". Specifically, I am expecting 1, but getting 0.
One possibility I considered is dividing each number by a factor to make each of them smaller. Is there any other solution?
Javascript's Number type is a numeric data type in the double-precision 64-bit floating point format (IEEE 754).
If you are dealing with large integers, use a BigInt or a corresponding library.
I you don't want to rely on BigInt and only have positive integers in mind, you can also write the successor test yourself. Full code in the snippet below.
Notes
A string representation of a positive integer is easily convertible to a decimal array where the index represents the exponent to the base 10. For example "42" ~> [2, 4] (since 42 = 2*10^0 + 4*10^1). You can also just as easily convert it back.
Now for the successor test you just need to define the increment operation (which is just adding 1 with carry). With that you can just compare if the increment of one number is equal to the unincremented other number (and vice versa).
Code
// Convert a string representation of positive decimal integer to an array of decimals.
const toArray = numberString => Array.from(numberString, c => parseInt(c))
.reverse();
// Convert the array representation of a positive decimal integer string back to the corresponding string representation (this is the inverse of `toArray`).
const fromArray = numberArray => numberArray.map(String)
.reverse()
.join('');
console.log(fromArray(toArray("9007199254740993")) === "9007199254740993"); // true
// Perform the increment operation on the array representation of the positive decimal integer.
const increment = numberArray => {
let carry = 1;
const incrementedNumberArray = [];
numberArray.forEach(i => {
let j;
if (carry === 0) {
j = i;
} else if (carry === 1) {
if (i === 9) {
j = 0;
} else {
j = i + 1;
carry = 0;
}
}
incrementedNumberArray.push(j);
});
if (carry === 1) {
incrementedNumberArray.push(1);
}
return incrementedNumberArray;
};
console.log(fromArray(increment(toArray("9007199254740993"))) === "9007199254740994"); // true
console.log(fromArray(increment(toArray("9999999999999999"))) === "10000000000000000"); // true
// Test if two strings represent positive integers where one is the other's successor.
const isSuccessor = (a, b) => {
const a_ = increment(toArray(a));
const b_ = increment(toArray(b));
return fromArray(a_) === b || fromArray(b_) === a;
};
console.log(isSuccessor("9007199254740993", "9007199254740994")); // true
console.log(isSuccessor("9007199254740994", "9007199254740993")); // true
console.log(isSuccessor("9999999999999999", "10000000000000000")); // true
console.log(isSuccessor("10000000000000000", "9999999999999999")); // true
console.log(isSuccessor("10000000000000000", "10000000000000002")); // false
You can use BIG integer library like one in JAVA.
check here
npm install big-integer
var bigInt = require("big-integer");
var largeNumber1 = bigInt("9007199254740993");
var largeNumber2 = bigInt("9007199254740994"); // any other number
var ans = largeNumber1.minus(largeNumber2);
if(ans == 1 || ans == -1){
console.log('consecutive ')
}else{
console.log('not consecutive ')
}
Note: I recommend you to use BigInt(as suggested by #Andreas in comment), if you are dealing with Big Numbers.
UPDATED
Use this code to compare big positive integers(The arguments should be in string format)
function compareBigNumber(num1, num2) {
if (num1 > Number.MAX_SAFE_INTEGER && num2 > Number.MAX_SAFE_INTEGER) {
var newNum1 = num1.split('').reverse();
var newNum2 = num2.split('').reverse();
do {
newNum1.pop();
newNum2.pop();
} while (newNum1[newNum1.length-1] === '0' || newNum2[newNum2.length-1] === '0')
return compareBigNumber(newNum1.reverse().join(''), newNum2.reverse().join(''));
} else if(num1 > Number.MAX_SAFE_INTEGER){
return 'num1 is greater'
} else if (num2 > Number.MAX_SAFE_INTEGER) {
return 'num2 is greater'
}
else {
var num1Int = parseInt(num1);
var num2Int = parseInt(num2);
if (num1Int > num2Int) {
return 'Num1 is greater';
} else if (num2Int > num1Int){
return 'Num2 is greater'
} else {
return 'Num1 is equal to Num2';
}
}
}
console.log(compareBigNumber("9007199254740992", "9007199254740993"))
console.log(compareBigNumber("100000000000000000000", "0"))

How to make JS function faster/reduce complexity 0(n)/more efficient

I am working on some challenges on HackerRank and I am having some troubles with making functions faster/more efficient so that it does not timeout during the submit process. It usually times out for really large inputs (ex: string length of 1000 or more) with the number of loops I am using to get the function working. I know the loops make the complexity 0(n * n) or 0(n * n * n). I understand why the function is timing out because of the above complexity issue but I am not sure of how to make the function more efficient in order to handle larger inputs. I am a self-taught coder so please explain any answers thoroughly and simply so I can learn. Thanks!
Here is an example problem:
A string is said to be a special palindromic string if either of two conditions is met:
All of the characters are the same, e.g. aaa.
All characters except the middle one are the same, e.g. aadaa. (acdca will not satisfy this rule but aadaa will)
A special palindromic substring is any substring of a string which meets one of those criteria. Given a string, determine how many special palindromic substrings can be formed from it.
For example, given the string s = mnonopoo, we have the following special palindromic substrings:
m, n, o, n, o, p, o, o
oo
non, ono, opo
Function Description
Complete the substrCount function in the editor below. It should return an integer representing the number of special palindromic substrings that can be formed from the given string.
substrCount has the following parameter(s):
n: an integer, the length of string s
s: a string
function substrCount(n, s) {
//if each letter is its own palindrome then can start with length for count
let count = n;
//space used to get the right string slices
let space = 1;
//so we only get full strings with the split and no duplicates
let numberToCount = n;
for(let i = 0; i < n; i++){
for(let j = 0; j < n; j++){
//slice the string into the different sections for testing if palindrome
let str = s.slice(j, j+space);
if(numberToCount > 0){
//if it is an even length the all characters must be the same
if(str.length % 2 === 0){
let split = str.split('');
let matches = 0;
for(let k = 0; k < split.length; k++){
if(split[k] === split[k+1]){
matches++;
}
}
if(matches === split.length -1){
count++;
}
//if it is not even then we must check that all characters on either side
//of the middle are all the same
} else {
if(str.length > 1){
let splitMid = Math.floor(str.length / 2);
let firstHalf = str.slice(0, splitMid);
let lastHalf = str.slice(splitMid+1, str.length);
if(firstHalf === lastHalf){
if(str.length === 3){
count++;
} else {
let sNew = firstHalf + lastHalf;
let split = sNew.split('');
let matches = 0;
for(let k = 0; k < split.length; k++){
if(split[k] === split[k+1]){
matches++;
}
}
if(matches === split.length -1){
count++;
}
}
}
}
}
}
numberToCount--;
}
numberToCount = n-space;
space++;
}
return count;
}
i came up with a solution that i think is not too complex in terms of performance(one loop and a recursion at a time)
steps
split string and insert it into an array
check first for even pairs into a recursion
next check for odd pairs again into a recursion
check that the values inserted to final array are unique(not unique only for single chars)
please let me know if this is the correct solution or we can speed it up
const stirng = "mnonopoo";
const str = stirng.split("");
let finalArray = [];
str.forEach((x, index) => {
if (str[index] === str[index + 1]) {
checkEven(str, index, 1)
}
if (str[index - 1] === str[index + 1]) {
checkOdd(str, index, 0)
}
finalArray.push(x);
})
function checkOdd(str1, index, counter) {
if (str1[index - counter] === str1[index + counter]) {
counter++;
checkOdd(str1, index, counter);
} else {
pushUnique(finalArray, str1.slice(index - counter + 1, index + counter).join(""));
return str1.slice(index - counter, index + counter).join("")
}
}
function checkEven(str1, index, counter) {
if (str1[index] === str1[index + counter]) {
counter++;
checkEven(str1, index, counter);
} else {
pushUnique(finalArray, str1.slice(index, index + counter).join(""));
return;
}
}
function pushUnique(array, value) {
if (array.indexOf(value) === -1) {
array.push(value);
}
}
console.log(finalArray)
Since your only looking for special palindromes, and not all palindromes, that makes reducing complexity a bit easier, but even then, there will be some special cases, like "abababababababa....". No way I can see to reduce the complexity of that one too far.
I'd approach this like so. Start by grouping all the repeating numbers. I'm not sure of the best way to do that, but I'm thinking maybe create an array of objects, with object properties of count and letter.
Start with your totalCount at 0.
Then, select all objects with a count of 1, and check the objects to the left and right of them, and if they have the same letter value, take the MAX count, and add that value + 1 to your totalCount (the +1 being to account for the single letter by itself). If the letter values on either side do not match, just add 1 (to account for the letter by itself).
That handles all the odd number palindromes. Now to handle the even number palindromes.
Select all the objects with a count > 1, and take their count value and add the series from 1-count to the totalCount. The formula for this is (count/2)*(1+count).
Example:
In the string you have a run of 4 A's. There are the special palindromes (a, a, a, a, aa, aa, aa, aaa, aaa, aaaa) in that, for a total of 10. (4/2)*(1+4)=10.
I don't know how much that will reduce your processing time, but I believe it should reduce it some.

Convert number to alphabet letter

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();
}

Check if a single character is changed to a string or if it was more than one character

Good day.
I need to check if a string was changed one or more than one character. eg:
var string = "Orange"; //default
var string2 = "Orange"; // Equals
var string3 = "Oronge"; // orOnge just 1
var string4 = "Orongo"; // orOngO 2 or more.
verificar(string, string2); // return 2
verificar(string, string3); // return 0
verificar(string, string4); // return 1
function verificar(a, b){
//Here I need the code which returns 0 if only one character is modified or 1 if it has been modified two or more characters, or 2 in case you have not changed anything.
}
Any suggestions?
Greetings!
What you're looking for is the Levenshtein Distance.
In information theory and computer science, the Levenshtein distance is a string metric for measuring the difference between two sequences. Informally, the Levenshtein distance between two words is the minimum number of single-character edits (i.e. insertions, deletions or substitutions) required to change one word into the other.
There are a number of implementations easily found with a Google search, such as this one.
This should get the job done if a and b are the same length. Loop through a, check if each character is changed and if so, add to count.
function verificar(a, b){
count = 0
for (var i = 0; i < a.length; i ++) {
if (a[i] != b[i]) {
count++
}
}
if (count == 0) {
return "Equal"
}
else if (count == 1) {
return "1 change"
}
else {
return "More than 1 change"
}
}
https://jsfiddle.net/gtqr3hx1/6/

How to check if a digit is used in a number multiple times

Example: We have the number 1122. I would like to check that if given number contains the digit 1 more than once. In this case, it should return true.
I need the code to be flexible, it has to work with any number, like 3340, 5660, 4177 etc.
You can easily "force" JS to coerce any numeric value to a string, either by calling the toString method, or concatenating:
var someNum = 1122;
var oneCount = (someNum + '').split('1').length;
by concatenating a number to an empty string, the variable is coerced to a string, so you can use all the string methods you like (.match, .substring, .indexOf, ...).
In this example, I've chosen to split the string on each '1' char, count and use the length of the resulting array. If the the length > 2, than you know what you need to know.
var multipleOnes = ((someNum + '').split('1').length > 2);//returns a bool, true in this case
In response to your comment, to make it flexible - writing a simple function will do:
function multipleDigit(number, digit, moreThan)
{
moreThan = (moreThan || 1) + 1;//default more than 1 time, +1 for the length at the end
digit = (digit !== undefined ? digit : 1).toString();
return ((someNum + '').split(digit).length > moreThan);
}
multipleDigit(1123, 1);//returns true
multipleDigit(1123, 1, 2);//returns false
multipleDigit(223344,3);//returns 3 -> more than 1 3 in number.
Use javascript's match() method. Essentially, what you'd need to do is first convert the number to a string. Numbers don't have the RegExp methods. After that, match for the number 1 globally and count the results (match returns an array with all matched results).
​var number = 1100;
console.log(number.toString().match(/1/g).length);​
function find(num, tofind) {
var b = parseInt(num, 10);
var c = parseInt(tofind, 10);
var a = c.split("");
var times = 0;
for (var i = 0; i < a.length; i++) {
if (a[i] == b) {
times++;
}
}
alert(times);
}
find('2', '1122');
Convert the number to a string and iterate over it. Return true once a second digit has been found, for efficiency.
function checkDigitRepeat(number, digit) {
var i, count = 0;
i = Math.abs(number);
if(isNaN(i)) {
throw(TypeError('expected Number for number, got: ' + number));
}
number = i.toString();
i = Math.abs(digit);
if(isNaN(i)) {
throw(TypeError('expected Number for digit, got: ' + digit));
}
digit = i.toString();
if(digit > 9) {
throw(SyntaxError('expected a digit for digit, got a sequence of digits: ' + digit));
}
for(i = 0; i < number.length; i += 1) {
if(number[i] === digit) {
count += 1;
if(count >= 2) { return true; }
}
}
return false;
}
In the event that you want to check for a sequence of digits, your solution may lie in using regular expressions.
var myNum = '0011';
var isMultipleTimes = function(num) {
return !!num.toString().match(/(\d)\1/g);
}
console.log(isMultipleTimes(myNum));
JavaScript Match
Using #Aspiring Aqib's answer, I made a function that actually works properly and in the way I want.
The way it works is:
Example execution: multDig('221','2')
Split the number (first argument) to an array where each element is one digit.Output: ['2','2','1']
Run a for loop, which checks each of the array elements if they match with the digit (second argument), and increment the times variable if there is a match.Output: 2
Check inside the for loop if the match was detected already to improve performance on longer numbers like 2211111111111111
Return true if the number was found more than once, otherwise, return false.
And finally the code itself:
function multDig(number, digit){
var finalSplit = number.toString().split(''), times = 0;
for (i = 0; i < finalSplit.length; i++){
if (finalSplit[i] == digit){
times++
}
if (times > 1){
return true;
}
}
return false;
}

Categories