iterate digits in a number as long as its the same number - javascript

I need to loop through digits of a number , until there is a difference in thats number , and then output the number length :
For example :
0000123
so the output should be 3.
(eliminate 0000 and output 123)
How can I tackle it ?

Try looping on string until you find difference:
var num="001234",i,max=num.length,output;
for(i=1;i<max;i+=1){
if(num[i]!== num[i-1]){
output = num.substring(i,max);
break;
}
}
alert(output);

You can use ES5 features like filter:
var n = '11112213133';
var test = true;
console.log(String(n).split('').filter(function(v,i,a) {
test = test? v == a[0] : test;
return !test;
}).join('')); // 2213133
You can also use simple string methods (which are probably hugely faster):
var n = '11112213133';
var i = 0, c = n.charAt(0);
while (c == n.charAt(++i)) {}
console.log(n.substr(i)); // 2213133
Though these will trim the first number whether it's repeated or not.

Related

What is the safest way to split a "Floating Point Number String" into its Whole and Fractional Parts

I have developed the following short function to split a number passed to it in a string format into its Whole and Fractional Parts (also outputted as strings).
Note1: The Whole part of the number can run into large numbers (in excess of 50 digits).
Note 2: The output result (the Whole and the Fraction strings) will not be converted into an integer or a float but will be further manipulated only as a string due to the Javascript rounding for large numbers. So going back to numbers is not a concern here
Because the function detects the machine's locale automatically, it is therefore expected that the user enters (passes) the number in the locale of his local machine or otherwise the number is generated programmatically and passed to the function.
The number is expected to be passed as a "string" due to the very large length and also because there is no handling for numbers passed in exponent (e) format.
The function uses the toLocaleString() to detect the decimal and thousand separators.
I have tested the function with the major number systems (.,' space) and so far, so good.
The question is, how safe will this code be, and are there any alternative better and safer methods to do it or corrections/changes necessary?
Thanks
function splitFloatString(NumString) {
var decimalSeparator = (1.1).toLocaleString().substring(1,2); // Get Decimal Separator
var thousandSeparator = (1000).toLocaleString().substring(1,2); // Get Thousands Separator
NumString += ""; // ensure a string
var fraction ="0"; // default no fractional part
NumString = NumString.replace(RegExp("\\"+thousandSeparator,"g"),""); //remove thousand separators if any
if (RegExp("\\"+decimalSeparator,"g").test(NumString)) { // test for decimal separator
var n = NumString.split(decimalSeparator); // Split at Decimal Seprator
NumString = n[0]; // The Whole part
if (n.length==2) fraction = n[1]; // The Fractional part
if (fraction=="") fraction ="0";
}
console.log("Whole: ("+NumString+"), Fraction: ("+fraction+")"); // added for testing
//return n=[NumString,fraction]; // normal return uncomment
}
//------------------------------------------------------------------------------------
// Tests assuming user's machine and user enters/passes US-EN separators as an example
//------------------------------------------------------------------------------------
splitFloatString("123456789123456699999887788812340786.45678907656912574321115194123123456789");
splitFloatString("1,234,567,891,234,566,999,998,888,812,340.456520754186789075194123123456789");
splitFloatString("200")
splitFloatString("0.")
splitFloatString(123456.2349999)
splitFloatString("")
splitFloatString()
According to me, you are just complicating the whole thing unnecessarily. Here's a simple way to achieve the same result.
function getLocaleSeparators() {
const testNumber = 1000.1.toLocaleString()
return [testNumber.substring(1,2), testNumber.substring(5,6)]
}
function splitFloatString(number) {
const numberString = number.toString()
const [thousandSeparator, decimalSeparator] = getLocaleSeparators()
let [wholePart, fractionPart] = numberString.replace(new RegExp(thousandSeparator, 'g'), '').split(decimalSeparator)
wholePart = wholePart || "0"
fractionPart = fractionPart || "0"
console.log(`Whole: ${wholePart}, Fraction: ${fractionPart}`);
}
function getLocaleSeparators() {
const testNumber = 1000.1.toLocaleString()
return [testNumber.substring(1,2), testNumber.substring(5,6)]
}
function splitFloatString(number) {
const numberString = number.toString()
const [thousandSeparator, decimalSeparator] = getLocaleSeparators()
let [wholePart, fractionPart] = numberString.replace(new RegExp(thousandSeparator, 'g'), '').split(decimalSeparator)
wholePart = wholePart || "0"
fractionPart = fractionPart || "0"
console.log(`Whole: ${wholePart}, Fraction: ${fractionPart}`);
}
splitFloatString("123456789123456699999887788812340786.45678907656912574321115194123123456789");
splitFloatString("1,234,567,891,234,566,999,998,888,812,340.456520754186789075194123123456789");
splitFloatString("200")
splitFloatString("0.")
splitFloatString(123456.2349999)
splitFloatString("")
I recommend you to use the math.floor function for such purposes.
It rounds the number passed as parameter to its nearest integer in downward direction:
Also, The Math.ceil() function rounds a number up to the next largest whole number or integer.
For other handy options, you can check out this https://www.w3docs.com/snippets/javascript/how-to-convert-a-float-number-to-whole-number-in-javascript.html
Please try with this one. might help you.
number = "21212.32323";
var numberString = number + ''; // converts into string
var index = numberString.lastIndexOf("."); // get the index
var strFloat, wholeStr;
if(index === -1) {
strFloat = '';
wholeStr = numberString.replace(/[^\w\s]/gi, '').replace(/ /g,'')
} else {
strFloat = numberString.substring(index + 1); // get the decimal part
var strWhole = numberString.substring(0, index); // get the number
wholeStr = strWhole.replace(/[^\w\s]/gi, '').replace(/ /g,'') // remove spcl character
}
console.log(`Whole: ${wholeStr}, Fraction: ${strFloat}`);
And yes you can not exceed MAX_SAFE_INTEGER in javascript i.e 32-bits.
What is JavaScript's highest integer value that a number can go to without losing precision?
Have been able to finally get the final answer I was looking for.
Thanks to all for their assistance and ideas:
function numberSplit (NumString) {
var decimalSep = 1.1.toLocaleString().substring(1,2), // Get Deciaml Separator
thousandSep = 1e3.toLocaleString().substring(1,2), // Get Thousand Separator
fraction = "0", // Default "0"
n = (NumString = (NumString +="").replace(RegExp("\\"+thousandSep,"g"),"")).split(decimalSep);
NumString = n[0] ; // Get Whole Part
NumString == "" && (NumString = undefined); // Whole = undefined if empty
n.length == 2 && (fraction = n[1]); // Get Fractional part (only if 1 decimal place)
fraction == "" && (fraction = "0"); // Fraction = 0 if empty
console.log("Whole: ("+NumString+"), Fraction: ("+fraction+")")
}
//-----------------------------------------------------------
// Ttests assuming user enters US-EN separators as an example
//-----------------------------------------------------------
numberSplit("123456789123456699999887788812340786.45678907656912574321115194123123456789");
numberSplit("1,234,567,891,234,566,999,998,888,812,340.456520754186789075194123123456789");
numberSplit("200")
numberSplit("0.")
numberSplit(123456.2349999)
numberSplit("1.2.3"); // Fractional part ignored as invalid
numberSplit("") // Return undefined
numberSplit() // Return undefined
numberSplit(NaN) // Return NaN
numberSplit(undefined) // Return undefined

convert number to string returns empty if number 0

Trying to convert string to a number, works fine apart from when the number is zero it returns an empty string;
I understand 0 is false, but I just need a neat way of it returning the string "0"
I'm using:
const num = this.str ? this.str.toString() : '' ;
I even thought of using es6 and simply ${this.str} but that didn't work
Because 0 is "false-y" in JavaScript, as you've already figured out, you can't utilized it in a conditional. Instead, ask yourself what the conditional is really trying to solve.
Are you worried about null / undefined values? Perhaps this is better:
const num = (typeof this.str !== "undefined" && this.str !== null) ? this.str.toString() : "";
Odds are you really only care if this.str is a Number, and in all other cases want to ignore it. What if this.str is a Date, or an Array? Both Date and Array have a .toString() method, which means you may have some weird bugs crop up if one slips into your function unexpectedly.
So a better solution may be:
const num = (typeof this.str === "number") ? this.str.toString() : "";
You can also put your code in a try catch block
const num = ''
try {
num = this.str.toString();
} catch(e) {
// Do something here if you want.
}
Just adding to given answers - if you do:
x >> 0
you will convert anything to a Number
'7' >> 0 // 7
'' >> 0 // 0
true >> 0 // 1
[7] >> 0 // 7
It's a right shift bit operation. You can do magic with this in many real life cases, like described in this article.
In my case, the zero (number) that I wanted to converted to a string (which was the value of an option in a select element) was a value in an enum.
So I did this, since the enum was generated by another process and I could not change it:
let stringValue = '';
if (this.input.enumValue === 0) {
stringValue = '0';
} else {
stringValue = this.input.enumValue.toString();
}

Letter Count I JavaScript Challenge on Coderbyte

I've been on this problem for several hours now and have done all I can to the best of my current newbie javaScript ability to solve this challenge but I just can't figure out exactly what's wrong. I keep getting "UNEXPECTED TOKEN ILLEGAL on here: http://jsfiddle.net/6n8apjze/14/
and "TypeError: Cannot read property 'length' of null": http://goo.gl/LIz89F
I think the problem is the howManyRepeat variable. I don't understand why I'm getting it can't read the length of null when clearly word is a word from str...
I got the idea for:
word.toLowerCase().split("").sort().join("").match(/([.])\1+/g).length
...here: Get duplicate characters count in a string
The Challenge:
Using the JavaScript language, have the function LetterCountI(str) take the str
parameter being passed and return the first word with the greatest number of
repeated letters. For example: "Today, is the greatest day ever!" should return
greatest because it has 2 e's (and 2 t's) and it comes before ever which also
has 2 e's. If there are no words with repeating letters return -1. Words will
be separated by spaces.
function LetterCountI(str){
var wordsAndAmount={};
var mostRepeatLetters="-1";
var words=str.split(" ");
words.forEach(function(word){
// returns value of how many repeated letters in word.
var howManyRepeat=word.toLowerCase().split("").sort().join("").match(/([.])\1+/g).length;
// if there are repeats(at least one value).
if(howManyRepeat !== null || howManyRepeat !== 0){
wordsAndAmount[word] = howManyRepeat;
}else{
// if no words have repeats will return -1 after for in loop.
wordsAndAmount[word] = -1;
}
});
// word is the key, wordsAndAmount[word] is the value of word.
for(var word in wordsAndAmount){
// if two words have same # of repeats pick the one before it.
if(wordsAndAmount[word]===mostRepeatLetters){
mostRepeatLetters=mostRepeatLetters;
}else if(wordsAndAmount[word]<mostRepeatLetters){
mostRepeatLetters=mostRepeatLetters;
}else if(wordsAndAmount[word]>mostRepeatLetters){
mostRepeatLetters=word;
}
}
return mostRepeatLetters;
}
// TESTS
console.log("-----");
console.log(LetterCountI("Today, is the greatest day ever!"));
console.log(LetterCountI("Hello apple pie"));
console.log(LetterCountI("No words"));
Any guidance is much appreciated. Thank you!! ^____^
Here is the working code snippet:
/*
Using the JavaScript language, have the function LetterCountI(str) take the str
parameter being passed and return the first word with the greatest number of
repeated letters. For example: "Today, is the greatest day ever!" should return
greatest because it has 2 e's (and 2 t's) and it comes before ever which also
has 2 e's. If there are no words with repeating letters return -1. Words will
be separated by spaces.
console.log(LetterCountI("Today, is the greatest day ever!") === "greatest");
console.log(LetterCountI("Hello apple pie") === "Hello");
console.log(LetterCountI("No words") === -1);
Tips:
This is an interesting problem. What we can do is turn the string to lower case using String.toLowerCase, and then split on "", so we get an array of characters.
We will then sort it with Array.sort. After it has been sorted, we will join it using Array.join. We can then make use of the regex /(.)\1+/g which essentially means match a letter and subsequent letters if it's the same.
When we use String.match with the stated regex, we will get an Array, whose length is the answer. Also used some try...catch to return 0 in case match returns null and results in TypeError.
/(.)\1+/g with the match method will return a value of letters that appear one after the other. Without sort(), this wouldn't work.
*/
function LetterCountI(str){
var wordsAndAmount={};
var mostRepeatLetters="";
var words=str.split(" ");
words.forEach(function(word){
var howManyRepeat=word.toLowerCase().split("").sort().join("").match(/(.)\1+/g);
if(howManyRepeat !== null && howManyRepeat !== 0){ // if there are repeats(at least one value)..
wordsAndAmount[word] = howManyRepeat;
} else{
wordsAndAmount[word] = -1; // if no words have repeats will return -1 after for in loop.
}
});
// console.log(wordsAndAmount);
for(var word in wordsAndAmount){ // word is the key, wordsAndAmount[word] is the value of word.
// console.log("Key = " + word);
// console.log("val = " + wordsAndAmount[word]);
if(wordsAndAmount[word].length>mostRepeatLetters.length){ //if two words have same # of repeats pick the one before it.
mostRepeatLetters=word;
}
}
return mostRepeatLetters ? mostRepeatLetters : -1;
}
// TESTS
console.log("-----");
console.log(LetterCountI("Today, is the greatest day ever!"));
console.log(LetterCountI("Hello apple pie"));
console.log(LetterCountI("No words"));
/*
split into words
var wordsAndAmount={};
var mostRepeatLetters=0;
loop through words
Check if words has repeated letters, if so
Push amount into object
Like wordsAndAmount[word[i]]= a number
If no repeated letters...no else.
Loop through objects
Compare new words amount of repeated letters with mostRepeatLetters replacing whoever has more.
In the end return the result of the word having most repeated letters
If all words have no repeated letters return -1, ie.
*/
The changes made:
[.] turned into . as [.] matches a literal period symbol, not any character but a newline
added closing */ at the end of the code (the last comment block was not closed resulting in UNEXPECTED TOKEN ILLEGAL)
if(howManyRepeat !== null || howManyRepeat !== 0) should be replaced with if(howManyRepeat !== null && howManyRepeat !== 0) since otherwise the null was testing for equality with 0 and led to the TypeError: Cannot read property 'length' of null" issue. Note that .match(/(.)\1+/g).length cannot be used since the result of matching can be null, and this will also cause the TypeError to appear.
The algorithm for getting the first entry with the greatest number of repetitions was wrong since the first if block allowed subsequent entry to be output as a correct result (not the first, but the last entry with the same repetitions was output actually)
-1 can be returned if mostRepeatLetters is empty.
Hope you dont mind if I rewrite this code. My code may not be that efficient.
Here is a snippet
function findGreatest() {
// ipField is input field
var getString = document.getElementById('ipField').value.toLowerCase();
var finalArray = [];
var strArray = [];
var tempArray = [];
strArray = (getString.split(" "));
// Take only those words which has repeated letter
for (var i = 0, j = strArray.length; i < j; i++) {
if ((/([a-zA-Z]).*?\1/).test(strArray[i])) {
tempArray.push(strArray[i]);
}
}
if (tempArray.length == 0) { // If no word with repeated Character
console.log('No such Word');
return -1;
} else { // If array has words with repeated character
for (var x = 0, y = tempArray.length; x < y; x++) {
var m = findRepWord(tempArray[x]); // Find number of repeated character in it
finalArray.push({
name: tempArray[x],
repeat: m
})
}
// Sort this array to get word with largest repeated chars
finalArray.sort(function(z, a) {
return a.repeat - z.repeat
})
document.getElementById('repWord').textContent=finalArray[0].name;
}
}
// Function to find the word which as highest repeated character(s)
function findRepWord(str) {
try {
return str.match(/(.)\1+/g).length;
} catch (e) {
return 0;
} // if TypeError
}
Here is DEMO
function LetterCountI(str) {
var word_arr = str.split(" ");
var x = word_arr.slice();
for(var i = 0; i < x.length; i ++){
var sum = 0;
for(var y = 0; y < x[i].length; y++){
var amount = x[i].split("").filter(function(a){return a == x[i][y]}).length;
if (amount > 1){
sum += amount
}
}
x[i] = sum;
}
var max = Math.max.apply(Math,x);
if(max == 0)
return -1;
var index = x.indexOf(max);
return(word_arr[index]);
};
Here is another version as well.
You could use new Set in the following manner:
const letterCount = s => {
const res = s.split(' ')
.map(s => [s, (s.length - new Set([...s]).size)])
.reduce((p, c) => (!p.length) ? c
: (c[1] > p[1]) ? c : p, []);
return !res[1] ? -1 : res.slice(0,1).toString()
}
Note: I have not tested this solution (other than the phrases presented here), but the idea is to subtract unique characters from the total characters in each word of the phrase.

javascript Binary operation don't work for options

Here is what i have...
some array item have option that is binary
like
$item[0] = 0010
$item[1] = 1000
$item[2] = 0110
$item[3] = 1101
each bit represent some option
what i need is to compare it to the customer request option
let's say it's 0010
so i need the logic to show only $item[0] and $item[2] because second byte is 1. BUT, when there is no customer options check : 0000 i must show them all
only when some options are show there must be filter...
i should have listen more in my math class... i am clueless now, please help !
note :
everything come from here : http://jsfiddle.net/yHxue/
but i dont understand this line :
markers[m].setMap(((markers[m].props & props)>>>0===props)? ((props)?map:null): null);, so i have rewritten it, mine don't work !
If your data is actual numbers, then just use the bitwise & operator on each member.
var customerOption = parseInt("0010", 2)
$item.forEach(function(n, i) {
if (customerOption === 0 || ((n & customerOption) == customerOption))
alert(i); // show this item
});
If they're strings, then you'll need to convert each item to a number first.
Same as above, but...
parseInt(n, 2);
var $item = [];
$item[0] = "0010"
$item[1] = "1000"
$item[2] = "0110"
$item[3] = "1101"
var customerOption = parseInt("0010", 2)
$item.forEach(function(n, i) {
if (customerOption === 0 || ((parseInt(n, 2) & customerOption) == customerOption))
document.querySelector("pre").textContent += "\n0010 matched index: " + i;
});
document.querySelector("pre").textContent += "\n\n"
var customerOption = parseInt("0110", 2)
$item.forEach(function(n, i) {
if (customerOption === 0 || ((parseInt(n, 2) & customerOption) == customerOption))
document.querySelector("pre").textContent += "\n0110 matched index: " + i;
});
<pre></pre>
Convert all the strings (items as well as the mask) to a number using parseInt(string, 2).
If mask is 0, just take all the items. If not:
Then use the & operator to see the common 1 bits:
var common = item & mask;
Then test common:
If you want any of the mask bits, then common should just not be 0.
If you want all of the mask bits, then common should equal mask.
EDIT:
markers[m].setMap(
((markers[m].props & props) >>> 0 === props) ?
((props) ? map : null) :
null
);
markers[m].props & props looks for common 1 bits, as I explain above; >>> 0 makes sure the number is positive. The result is tested against props, making sure the common bits are all the bits in props (as in my second option above). If all the props bits are set, and if props is not zero, then markers[m] is setMap-ped to map; otherwise, to null.
var selections = ['0010', '1000', '0110', '1111'];
var getRequiredSelections = function (customerSelection) {
var customerSelectionInt = parseInt(customerSelection, 2);
if (customerSelectionInt) {
return selections.filter(function (binaryString) {
return parseInt(binaryString, 2) & customerSelectionInt;
});
} else {
return selections;
}
};
You can use it like so:
getRequiredSelections('0010');
BUT, when there is no customer options check : 0000 i must show them all
In 2's compliment, -1 is all 1 in binary
if (!props) props = -1;
Testing for something in binary exactly, use both & and ===
needle === (needle & haystack)
This means looking for needle = 1001 in haystack = 0001 is false, even though 1001 & 0001 is the truthy 0001
You may not want to use exact matches in your case
You could write some code that takes callbacks to process your array
function applyByFlag(flag, callbackTrue, callbackFalse) {
if (!flag)
flag = -1;
function nop() {}
if (!callbackTrue) callbackTrue = nop;
if (!callbackFalse) callbackFalse = nop;
boxes.forEach(function (e, i, a) {
if (flag & e) // not exact test
callbackTrue.call(e, e, i, a);
else
callbackFalse.call(e, e, i, a);
});
}
Of course, you'd probably want to adjust the test to work against e.props
The code you have is almost there; just add an additional check for when props is zero:
for(var m=0; m < markers.length; m++) {
var show = (markers[m].props & props)>>>0===props || props == 0;
markers[m].setMap(show ? map : null);
}
Demo
The markers[m].props & props expression will either be 0 (if not all bits of props match) or the value of props itself (if all bits of props match).
The additional >>>0 will turn the expression into an unsigned 32-bit integer value, but it's not necessary if you use the following expression:
var show = (markers[m].props & props) || props == 0;

How to increment a numeric string by +1 with Javascript/jQuery

I have the following variable:
pageID = 7
I'd like to increment this number on a link:
$('#arrowRight').attr('href', 'page.html?='+pageID);
So this outputs 7, I'd like to append the link to say 8. But if I add +1:
$('#arrowRight').attr('href', 'page.html?='+pageID+1);
I get the following output: 1.html?=71 instead of 8.
How can I increment this number to be pageID+1?
Try this:
parseInt(pageID, 10) + 1
Accordint to your code:
$('#arrowRight').attr('href', 'page.html?='+ (parseInt(pageID, 10) + 1));
+ happens to be valid operator for both strings and numbers that gives different results when both arguments are numeric and when at least one is not. One of possible workarounds is to use operator that only have numeric context but gives same mathematical result, like -. some_var - -1 will always be same as adding 1 to some_var's numeric value, no matter if it is string or not.
$('#arrowRight').attr('href', 'page.html?='+ (pageID - -1));
All these solutions assume that your number you want to add 1 to is within the machine precision for an integer. So if you have a large enough number within that string when you add 1 to it won't change the number.
For Example:
parseInt('800000000000000000', 10) + 1 = 800000000000000000
So I wrote a quick solution to the problem
function addOne(s) {
let newNumber = '';
let continueAdding = true;
for (let i = s.length - 1; i>= 0; i--) {
if (continueAdding) {
let num = parseInt(s[i], 10) + 1;
if (num < 10) {
newNumber += num;
continueAdding = false;
} else {
newNumber += '0';
}
} else {
newNumber +=s[i];
}
}
return newNumber.split("").reverse().join("");
}
Now, using the same example above
addOne('800000000000000000') + 1 = '800000000000000001'
Note that it must stay as a string or you will lose that 1 at the end.
It needs to be a integer, not a string. Try this:
pageID = parseInt(pageID)+1;
Then you can do
$('#arrowRight').attr('href', 'page.html?='+pageID);
Simply, $('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The parentheses makes the calculation done first before string concatenation.
let pageId = '7'
pageId++
console.log(pageId)
Nowadays, you just need to pageID++.
Just change your order of operations by wrapping your addition in parentheses; if pageID is already a number, parseInt() isn't necessary:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
Demo
As long as your pageID is numeric, this should be sufficient:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The problem you were seeing is that JavaScript normally executes in left-to-right order, so the string on the left causes the + to be seen as a concatenator, so it adds the 7 to the string, and then adds 1 to the string including 7.

Categories

Resources