I need to validate that the first two digits of a number which are not consecutive or equal.
This is for a ReactJS project, using a conditional "for" and "if" to achieve the validation.
I have this code:
for (let i = 0; i < arrayPassword.length - 1; i++)
{
const actual = parseInt(arrayPassword[i])
const next = parseInt(arrayPassword[i + 1])
//validate consecutive and equal numbers
let isConsecutive = actual + 1 === next || actual === next ? true : false;
if (isConsecutive) {
callback(`consecutive and equal numbers are not allow.`);
} else {
callback();
}
}
At this moment I can validate the full expression when I have a 4 digits consecutive or equal, for example:
(1111, 2222, 3333, 1234, 2345, 6789, ...)
and it's ok, but the problem appears when the first two digits are equal or consecutive, for example:
(1147, 2293, 3360, 1244, 6750, 8952, ...)
I hope that through a condition the numbers like the previous examples do not enter the conditional If.
I appreciate the interest in helping me.
I believe that this simple function do what you need - checks if any two adjacent numbers in a password array are equal or consecutive
function neighboursAreEqual(arrayPassword) {
for (var i = 0; i < arrayPassword.length - 1; i++) {
const current = parseInt(arrayPassword[i]);
const next = parseInt(arrayPassword[i + 1]);
if (current === next || Math.abs(current - next) === 1) return true;
}
return false;
}
// to test how it works
console.log(neighboursAreEqual([])) // false (no symbols to compare)
console.log(neighboursAreEqual(['1'])) // false (no neighboring symbol)
console.log(neighboursAreEqual(['1', '2'])) // true (consecutive)
console.log(neighboursAreEqual(['1', '3'])) // false
console.log(neighboursAreEqual(['2', '2'])) // true(equal)
console.log(neighboursAreEqual(['0', '2', '4'])) // false
console.log(neighboursAreEqual(['0', '2', '3'])) // true (consecutive)
console.log(neighboursAreEqual(['0', '8', '2', '2'])) // true (consecutive)
If you need to compare only first two symbols in array (though I don't know the reason for such requirement) the function becomes even easier - you won't even need for there...
There's no way to know that a number is invalid before looking at all its digits, but your code calls the callback within the loop, after looking at only two. In fact, the callback is called three times, once on each iteration. To fix it, keep track of each validity check in a separate variable, and only call the callback after the loop completes:
let equalSoFar = true;
let consecutiveSoFar = true;
for (let i = 0; i < arrayPassword.length - 1; i++) {
const actual = parseInt(arrayPassword[i])
const next = parseInt(arrayPassword[i + 1])
// validate equal numbers
// "equalSoFar &&" because after a nonequal digit is encountered, equalSoFar MUST be false
equalSoFar = equalSoFar && actual === next;
// validate consecutive numbers
// "consecutiveSoFar &&": same logic
consecutiveSoFar = consecutiveSoFar && actual + 1 === next;
}
if (equalSoFar || consecutiveSoFar) {
callback(`consecutive and equal numbers are not allowed.`);
} else {
callback();
}
You can also break each validity check into its own function and examine the number array with Array.every. A number array has all equal digits if each of its digits is equal to the first one. It has all consecutive digits if each digit is equal to the first one plus its index in the array.
function allSameDigit(array) {
return array.every(digit => digit === array[0]);
}
function allConsecutiveDigits(array) {
return array.every((digit, index) => +digit === +array[0] + index);
}
function isValid(array) {
return !allSameDigit(array) && !allConsecutiveDigits(array);
}
const testValues = [1111, 2222, 3333, 1234, 2345, 6789, 1147, 2293, 3360, 1244, 6750, 8952]
.map(num => num.toString().split(''));
for (let arr of testValues)
console.log(`${arr.join('')}: ${isValid(arr) ? 'valid' : 'invalid'}`);
Related
I'm writing a function that will return true or false in regards to whether or not the input string is in alphabetical order. I'm getting undefined and not sure what I'm missing
function is_alphabetic(str) {
let result = true;
for (let count = 1, other_count = 2; count >= str.length - 1, other_count >= str.length; count++,
other_count++) {
if (str.at[count] > str.at[other_count]) {
let result = false
}
return result
}
}
console.log(is_alphabetic('abc'));
you have put return statement inside the for loop, it should be outside the loop body.
Your code is also not correct. count should start from 0, other_count should start from 1.
count >= str.length - 1 should be count < str.length - 1 (this condition is completely unnecessary in your code because other_count < str.length should be the terminating condition in the loop)
and
other_count >= str.length should be other_count < str.length
Here's your corrected code
function is_alphabetic(str) {
let result = true;
for (let count = 0, other_count = 1; other_count < str.length; count++, other_count++) {
if (str[count] > str[other_count]) {
result = false
}
}
return result;
}
console.log(is_alphabetic('abc'));
Here's an alternative approach
function is_alphabetic(str){
return str.split('')
.every((c, idx) => str[idx + 1] ? c < str[idx + 1] : true);
}
console.log(is_alphabetic('abc'));
Keep in mind that if you want the comparisons between the characters to be case-insensitive, then convert the string in to lowercase before comparing the characters.
I think is easier if you compare the string using this function:
var sortAlphabets = function(text) {
return text.split('').sort().join('');
};
This produces results like:
sortAlphabets("abghi")
output: "abghi"
Or:
sortAlphabets("ibvjpqjk")
output: "bijjkpqv"
if you want to know if your string is alphabetically sorted, you might use:
var myString = "abcezxy"
sortAlphabets(myString) == myString
output: false
Or in case, you want to create an specific function:
function isSorted(myString) {
return sortAlphabets(myString) == myString
}
And for that case, you can use:
isSorted("abc")
var sortAlphabets = function(text) {
return text.split('').sort().join('');
};
function isSorted(myString) {
return sortAlphabets(myString) == myString
}
alert("is abc sorted: " + isSorted("abc"));
alert("is axb sorted: " + isSorted("axb"));
This should do it. I used .localeCompare() as this will ignore small/capital differences and will also deal reasonably with language specific characters, like German Umlauts.
function is_alphabetic(str){
return !str.split('').some((v,i,a)=>i&&v.localeCompare(a[i-1])<0)
}
['abcdefg','aacccRt','ashhe','xyz','aüv'].forEach(s=> console.log(s,is_alphabetic(s)) );
There are two issues in your code:
Your return statement is in your for-loop. To avoid such mistakes you can get a code-formatter like prettier;
Your for-loop condition is invalid. Keep in mind that the second part of the for-loop statement is supposed to be true to do an iteration and false to stop doing iterations. In this case, your condition count >= str.length-1, other_count >= str.length will first evaluate count >= str.length-1, discard the result because of the comma operator, evaluate other_count >= str.length which immediately resolves to false.
These two things together make it so your function never returns, which the javascript runtime interprets as undefined.
Hope this helps you understand what went wrong. But like many other pointed out, there are better ways to tackle the problem you're trying to solve.
You just have to compare the string with its corresponding 'sorted' one
let string = 'abc'.split('').join('');
let sortedString = 'abc'.split('').sort().join('');
console.log(sortedString === sortedString)
let string2 = 'dbc'.split('').join('');
let sortedString2 = 'dbc'.split('').sort().join('');
console.log(string2 === sortedString2)
I'm doing a kata on Codewars. I'm supposed to write a function that returns the index of which number, is not like the others, in evenness(i.e. [1, 2, 4] should return 0). I believe I have a solution, and it proves true when copy/pasting the code, and console.logging on freecodecamps live server, however, when i try to run the code where it is written, it only passes one test. What is going wrong here?
I've tried testing with console.logs, and my solution holds. I know I could just use filter to solve the problem, but i wan't to practice fundamentals.
let odd = [];
let even = [];
function isEven(num) {
if (num % 2 === 0) {
return true;
} else {
return false;
}
}
function iqTest(numbers) {
let nums = numbers.split(' ').map(function(item) {
return parseInt(item, 10);
})
for (let i in nums) {
if (isEven(nums[i])) {
even.push(nums[i])
} else {
odd.push(nums[i])
}
}
if (even.length > odd.length) {
return nums.indexOf(odd[0]) + 1;
} else {
return nums.indexOf(even[0]) + 1;
}
}
The function should accept a string of numbers, one of which will not be either even or odd, then return the index of that number + 1.
You could take the in comments mentioned approach and search for at least one odd and one even and one additional item, at least three items and exit early if this combination is found.
No need to convert the values in advance, because the value get converted to number by using the remainder operator of isEven function.
For a faster return value store the index instead of the value and omit a later indexOf seach.
function isEven(i) { return i % 2 === 0; }
function iqTest(numbers) {
var even = [], odd = [], values = numbers.split(' ');
for (let i = 0; i < values.length; i++) {
(isEven(values[i]) ? even : odd).push(i);
if (even.length && odd.length && even.length + odd.length > 2)
return (even.length < odd.length ? even : odd)[0] + 1;
}
}
console.log(iqTest("1 2 4")); // 1
console.log(iqTest("2 4 7 8 10")) // 3
console.log(iqTest("1 2 1 1")); // 2
I want to identify strings that are made up exclusively of same-length character groups. Each one of these groups consists of at least two identical characters. So, here are some examples:
aabbcc true
abbccaa false
xxxrrrruuu false (too many r's)
xxxxxfffff true
aa true (shortest possible positive example)
aabbbbcc true // I added this later to clarify my intention
#ilkkachu: Thanks for your remark concerning the repetition of the same character group. I added the example above. Yes, I want the last sample to be tested as true: a string made up of the two letter groups aa, bb, bb, cc.
Is there a simple way to apply this condition-check on a string using regular expressions and JavaScript?
My first attempt was to do something like
var strarr=['aabbcc','abbccaa','xxxrrrruuu',
'xxxxxfffff','aa','negative'];
var rx=/^((.)\2+)+$/;
console.log(strarr.map(str=>str+': '+!!str.match(rx)).join('\n'));
It does look for groups of repeated characters but does not yet pay attention to these groups all being of the same length, as the output shows:
aabbcc: true
abbccaa: false
xxxrrrruuu: true // should be false!
xxxxxfffff: true
aa: true
aabbbbcc: true
negative: false
How do I get the check to look for same-length character groups?
To get all the groups of the same character has an easy regex solution:
/(.)\1*/g
Just repeating the backreference \1 of the character in capture group 1.
Then just check if there's a length in the array of same character strings that doesn't match up.
Example snippet:
function sameLengthCharGroups(str)
{
if(!str) return false;
let arr = str.match(/(.)\1*/g) //array with same character strings
.map(function(x){return x.length}); //array with lengths
let smallest_length = arr.reduce(function(x,y){return x < y ? x : y});
if(smallest_length === 1) return false;
return arr.some(function(n){return (n % smallest_length) !== 0}) == false;
}
console.log("-- Should be true :");
let arr = ['aabbcc','xxxxxfffff','aa'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should also be true :");
arr = ['aabbbbcc','224444','444422',
'666666224444666666','666666444422','999999999666666333'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should be false :");
arr = ['abbcc','xxxrrrruuu','a','ab','',undefined];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
ECMAScript 6 version with fat arrows (doesn't work in IE)
function sameLengthCharGroups(str)
{
if(!str) return false;
let arr = str.match(/(.)\1*/g)
.map((x) => x.length);
let smallest_length = arr.reduce((x,y) => x < y ? x : y);
if(smallest_length === 1) return false;
return arr.some((n) => (n % smallest_length) !== 0) == false;
}
Or using exec instead of match, which should be faster for huge strings.
Since it can exit the while loop as soon a different length is found.
But this has the disadvantage that this way it can't get the minimum length of ALL the lengths before comparing them.
So those with the minimum length at the end can't be found as OK this way.
function sameLengthCharGroups(str)
{
if(!str) return false;
const re = /(.)\1*/g;
let m, smallest_length;
while(m = re.exec(str)){
if(m.index === 0) {smallest_length = m[0].length}
if(smallest_length > m[0].length && smallest_length % m[0].length === 0){smallest_length = m[0].length}
if(m[0].length === 1 ||
// m[0].length !== smallest_length
(m[0].length % smallest_length) !== 0
) return false;
}
return true;
}
console.log("-- Should be true :");
let arr = ['aabbcc','xxxxxfffff','aa'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should also be true :");
arr = ['aabbbbcc','224444','444422',
'666666224444666666','666666444422','999999999666666333'];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
console.log("-- Should be false :");
arr = ['abbcc','xxxrrrruuu','a','ab','',undefined];
arr.forEach(function(s){console.log(sameLengthCharGroups(s)+' : '+ s)});
Here's one that runs in linear time:
function test(str) {
if (str.length === 0) return true;
let lastChar = str.charAt(0);
let seqLength = 1;
let lastSeqLength = null;
for (let i = 1; i < str.length; i++) {
if (str.charAt(i) === lastChar) {
seqLength++;
}
else if (lastSeqLength === null || seqLength === lastSeqLength) {
lastSeqLength = seqLength;
seqLength = 1;
lastChar = str.charAt(i);
}
else {
return false;
}
}
return (lastSeqLength === null || lastSeqLength === seqLength);
}
Since requirements changed or weren't clear as now this is the third solution I'm posting. To accept strings that could be divided into smaller groups like aabbbb we could:
Find all lengths of all different characters which are 2 and 4 in this case.
Push them into an array named d.
Find the lowest length in set named m.
Check if all values in d have no remainder when divided by m
Demo
var words = ['aabbbcccdddd', 'abbccaa', 'xxxrrrruuu', 'xxxxxfffff', 'aab', 'aabbbbccc'];
words.forEach(w => {
var d = [], m = Number.MAX_SAFE_INTEGER;
var s = w.replace(/(.)\1+/gy, x => {
d.push(l = x.length);
if (l < m) m = l;
return '';
});
console.log(w + " => " + (s == '' && !d.some(n => n % m != 0)));
});
Using sticky flag y and replace method you could do this much more faster. This trick replaces occurrences of first one's length with an empty string (and stops as soon as an occurrence with different length happens) then checks if there are some characters left:
var words = ['aabbcc', 'abbccaa', 'xxxrrrruuu', 'xxxxxfffff', 'aa'];
words.forEach(w => {
console.log(w + " => " + (w.replace(/(.)\1+/gy, ($0, $1, o) => {
return $0.length == (o == 0 ? l = $0.length : l) ? '' : $0;
}).length < 1));
});
Another workaround would be using replace() along with test(). First one replaces different characters with their corresponding length and the second looks for same repeated numbers in preceding string:
var str = 'aabbc';
/^(\d+\n)\1*$/.test(str.replace(/(.)\1+/gy, x => x.length + '\n'));
Demo:
var words = ['aabbcc', 'abbccaa', 'xxxrrrruuu', 'xxxxxfffff', 'aa'];
words.forEach(w =>
console.log(/^(\d+\n)\1*$/.test(w.replace(/(.)\1+/gy, x => x.length + '\n')))
);
Since regex has never been my forte here's an approach using String#replace() to add delimiter to string at change of letter and then use that to split into array and check that all elements in array have same length
const values = ['aabbcc', 'abbccaa', 'xxxrrrruuu', 'xxxxxfffff', 'aa'];
const expect = [true, false, false, true, true];
const hasMatchingGroups = (str) => {
if(!str || str.length %2) return false;
const groups = str.replace(/[a-z]/g,(match, offset, string) => {
return string[offset + 1] && match !== string[offset + 1] ? match + '|' : match;
}).split('|');
return groups.every(s => s.length === groups[0].length)
}
values.forEach((s, i) => console.log(JSON.stringify([s,hasMatchingGroups(s), expect[i]])))
The length of the repeated pattern of same charcters needs to be specified within the regular expression. The following snippet creates regular expressions looking for string lengths of 11 down to 2. The for-loop is exited once a match is found and the function returns the length of the pattern found:
function pat1(s){
for (var i=10;i;i--)
if(RegExp('^((.)\\2{'+i+'})+$').exec(s))
return i+1;
return false;}
If nothing is found false is returned.
If the length of the pattern is not required, the regular expression can also be set up in one go (without the need of the for loop around it):
function pat2(s){
var rx=/^((.)\2)+$|^((.)\4{2})+$|^((.)\6{4})+$|^((.)\8{6})+$/;
return !!rx.exec(s);
}
Here are the results from both tests:
console.log(strarr.map(str=>
str+': '+pat1(str)
+' '+pat2(str)).join('\n')+'\n');
aabbcc: 2 true
abbccaa: false false
xxxrrrruuu: false false
xxxxxfffff: 5 true
aa: 2 true
aabbbbcc: 2 true
negative: false false
The regex in pat2 looks for certain repetition-counts only. When 1, 2, 4 or 6 repetitions of a previous character are found then the result is positive. The found patterns have lengths of 2,3,5 or 7 characters (prime numbers!). With these length-checks any pattern-length dividable by one of these numbers will be found as positive (2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,22,24,...).
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
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;
}