I'm sorry it's a stupid question but I'm try to list a sequence of numbers from 1 to a limit and they should be separated by comma. I have a problem. I don't know how to stop the comma. I should have 1,2,3 but I have ,1,2,3. Can you help me? Here is my code.
function getNumberSequence(number) {
var result = ""
if(number <= 0){
return result
}
else{
if(number == 1){
result = result + 1
} else {
for(i = 1; i <= number; i++){
result = result + ',' + i;
}
}
}
return result
}
Thanks for all
You can simply add a flag (in the example "first") and check if this is your first iteration - if so, don't add a comma but set it to false ... see here: http://jsfiddle.net/fdfxc5zq/
var first = true; //have a flag that tells you if this is your first iteration - don't add a comma the first time around
for (i = 0; i <= number; i++) {
if (first) {
first = false;
} else {
result += ", ";
}
result += i;
}
Using your code, simply declare result with an initial value of 1 and start the for loop with i=2. Solved. (And in case of number being 1, just return result)
A one-liner for you:
return Object.keys(Array.apply(null,new Array(number))).map(function(n) {return +n+1;}).join(",");
Basically, creates an array of length number, "applies" it (basically ends up giving undefined values to each index), then uses Object.keys to get the indices of the array, increments all the items, then joins the whole thing with commas.
Two easy methods:
1) Just add a comma after each number and return a substring of length-1 to get rid of the last comma
if (i === 0) return ""; //to avoid substring() issues on empty strings
var result = "";
for (i = 0; i <= number; i++) {
result = i + ",";
}
return result.substr(0, result.length-1);
2) Using array and join
var result = [];
for (i = 0; i <= number; i++) {
result.push(i)
}
return result.join(); //default join separator is the comma
YourCommaSeparatedString.split(',');
Related
I have a page with a grid where user's numbers get saved. It has a following pattern - every number ends with 3 digits after comma. It doesn't look nice, when for example user's input is
123,450
123,670
123,890
It's much better to have just 2 numbers after comma, because last 0 is absolutely meaningless and redundant.
The way it still should have 3 digits is only if at least one element in an array doesn't end up with 0
For example:
123,455
123,450
123,560
In this case 1st element of the array has the last digit not equal to 0 and hence all the elements should have 3 digits. The same story with 2 or 1 zeros
Zeros are redundant:
123,30
123,40
123,50
Zeros are necessary:
123,35
123,40
123,50
The question is how can I implement it programatically? I've started like this:
var zeros2Remove = 0;
numInArray.forEach(function(item, index, numInArray)
{
var threeDigitsAfterComma = item.substring(item.indexOf(',') + 1);
for(var j = 2; j <= 0; j--)
{
if(threeDigitsAfterComma[j] == 0)
{
zeros2Remove =+ 1;
}
else //have no idea what to do..
}
})
Well in my implementation I don't know how to do it since I have to iterate through every element but break it if at least 1 number has a last digit equal to zero.. In order to do that I have to break outer loop, but don't know how and I'm absolutely sure that I don't have to...
I think the following code what you are looking for exactly , please manipulate numbers and see the changes :
var arr = ["111.3030", "2232.0022", "3.001000", "4","558.0200","55.00003000000"];
var map = arr.map(function(a) {
if (a % 1 === 0) {
var res = "1";
} else {
var lastNumman = a.toString().split('').pop();
if (lastNumman == 0) {
var m = parseFloat(a);
var res = (m + "").split(".")[1].length;
} else {
var m = a.split(".")[1].length;
var res = m;
}
}
return res;
})
var maxNum = map.reduce(function(a, b) {
return Math.max(a, b);
});
arr.forEach(function(el) {
console.log(Number.parseFloat(el).toFixed(maxNum));
});
According to MDN,
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool. Use a plain loop or for...of instead.
If you convert your forEach loop to a for loop, you can break out of it with a label and break statement:
// unrelated example
let i;
let j;
outerLoop:
for (i = 2; i < 100; ++i) {
innerLoop:
for (j = 2; j < 100; ++j) {
// brute-force prime factorization
if (i * j === 2183) { break outerLoop; }
}
}
console.log(i, j);
I gave you an unrelated example because your problem doesn't need nested loops at all. You can find the number of trailing zeroes in a string with a regular expression:
function getTrailingZeroes (str) {
return str.match(/0{0,2}$/)[0].length;
}
str.match(/0{0,2}$/) finds between 0 and 2 zeroes at the end of str and returns them as a string in a one-element array. The length of that string is the number of characters you can remove from str. You can make one pass over your array of number-strings, breaking out when necessary, and use Array.map as a separate truncation loop:
function getShortenedNumbers (numInArray) {
let zeroesToRemove = Infinity;
for (const str of numInArray) {
let candidate = getTrailingZeroes(str);
zeroesToRemove = Math.min(zeroesToRemove, candidate);
if (zeroesToRemove === 0) break;
}
return numInArray.map(str => str.substring(0, str.length - zeroesToRemove);
}
All together:
function getTrailingZeroes (str) {
return str.match(/0{0,2}$/)[0].length;
}
function getShortenedNumbers (numInArray) {
let zeroesToRemove = Infinity;
for (const str of numInArray) {
let candidate = getTrailingZeroes(str);
zeroesToRemove = Math.min(zeroesToRemove, candidate);
if (zeroesToRemove === 0) break;
}
return numInArray.map(str => str.substring(0, str.length - zeroesToRemove));
}
console.log(getShortenedNumbers(['123,450', '123,670', '123,890']));
console.log(getShortenedNumbers(['123,455', '123,450', '123,560']));
This solution might seem a little cumbersome but it should work for all possible scenarios. It should be easy enough to make always return a minimal number of decimals places/leading zeros.
I hope it helps.
// Define any array
const firstArray = [
'123,4350',
'123,64470',
'123,8112390',
]
const oneOfOfYourArrays = [
'123,30',
'123,40',
'123,50',
]
// Converts 123,45 to 123.45
function stringNumberToFloat(stringNumber) {
return parseFloat(stringNumber.replace(',', '.'))
}
// For 123.45 you get 2
function getNumberOfDecimals(number) {
return number.split('.')[1].length;
}
// This is a hacky way how to remove traling zeros
function removeTralingZeros(stringNumber) {
return stringNumberToFloat(stringNumber).toString()
}
// Sorts numbers in array by number of their decimals
function byNumberOfValidDecimals(a, b) {
const decimalsA = getNumberOfDecimals(a)
const decimalsB = getNumberOfDecimals(b)
return decimalsB - decimalsA
}
// THIS IS THE FINAL SOLUTION
function normalizeDecimalPlaces(targetArray) {
const processedArray = targetArray
.map(removeTralingZeros) // We want to remove trailing zeros
.sort(byNumberOfValidDecimals) // Sort from highest to lowest by number of valid decimals
const maxNumberOfDecimals = processedArray[0].split('.')[1].length
return targetArray.map((stringNumber) => stringNumberToFloat(stringNumber).toFixed(maxNumberOfDecimals))
}
console.log('normalizedFirstArray', normalizeDecimalPlaces(firstArray))
console.log('normalizedOneOfOfYourArrays', normalizeDecimalPlaces(oneOfOfYourArrays))
Try this
function removeZeros(group) {
var maxLength = 0;
var newGroup = [];
for(var x in group) {
var str = group[x].toString().split('.')[1];
if(str.length > maxLength) maxLength = str.length;
}
for(var y in group) {
var str = group[y].toString();
var substr = str.split('.')[1];
if(substr.length < maxLength) {
for(var i = 0; i < (maxLength - substr.length); i++)
str += '0';
}
newGroup.push(str);
}
return newGroup;
}
Try it on jsfiddle: https://jsfiddle.net/32sdvzn1/1/
My script checks the length of every number decimal part, remember that JavaScript removes the last zeros in a decimal number, so 3.10 would be 3.1, so the length is less when there is a number with zeros in the end, in this case we just add a zero to the number.
Update
I've updated the script, the new version adds as much zeros as the different between the max decimal length and the decimal length of the analyzed number.
Example
We have: 3.11, 3.1423, 3.1
The max length would be: 4 (1423)
maxLenght (4) - length of .11 (2) = 2
We add 2 zeros to 3.11, that will become 3.1100
I think you can start out assuming you will remove two extra zeros, and loop through your array looking for digits in the last two places. With the commas, I'm assuming your numArray elements are strings, all starting with the same length.
var numArray = ['123,000', '456,100', '789,110'];
var removeTwo = true, removeOne = true;
for (var i = 0; i < numArray.length; i++) {
if (numArray[i][6] !== '0') { removeTwo = false; removeOne = false; }
if (numArray[i][5] !== '0') { removeTwo = false; }
}
// now loop to do the actual removal
for (var i = 0; i < numArray.length; i++) {
if (removeTwo) {
numArray[i] = numArray[i].substr(0, 5);
} else if (removeOne) {
numArray[i] = numArray[i].substr(0, 6);
}
}
I have written a function called reverseStr that takes in a string as a parameter and returns the string but with the characters in reverse.
For example: reverseStr('bootcamp'); => 'pmactoob'
Following is my program:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0; i <= splitStr.length -1 ; i++)
{
for(var j = splitStr.length - 1; j >= 0; j--)
{
reverseString[i] = splitStr[j]
}
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
If I run the function reverseStr("bootcamp") it returns bbbbbbbb.
Does anyone see a problem with the code?
Note: I DONOT WANT TO USE REVERSE() BUILT-IN FUNCTION
However, I found success with the following code but still need an answer to my initial question
function reverseStr(str)
{
var splitStr = str.split("");
reverseStr = "";
for(var i = splitStr.length - 1; i >= 0 ; i = i - 1)
{
reverseStr += splitStr[i];
}
return reverseStr;
}
You don't need to double-iterate through the characters, i.e., do not need to nest for loops. Iterate once and grab the chars in reverse order, like this:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0, j=splitStr.length-1; i <= splitStr.length -1 ; i++, j--)
{
reverseString[i] = splitStr[j]
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
You can see that here the loop goes on for as long as i <= splitStr.length -1,ie, length of the string. This is sufficient to get the mirroring character (i versus Array.length-i).
Here is a working snippet to demo:
var reverseStr = function(str) {
let result = String();
for(let i = str.length-1; i >= 0; i--) {
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
Perhaps a more elegant way to achieve the same (apart from Array.prototype.reverse()) would be to use String.prototype.chatAt(). This would avoid two conversions to and from an array, and also save you one variable. Granted, the code is much shorter and more obvious in what it is doing.
var reverseStr = function(str) {
let result = String(); // An empty string to store the result
for(let i = str.length-1; i >= 0; i--) { // Iterate backwards thru the chars and add to the result string
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''); // Original return method of the author
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
The problem is that your nested for loop runs its whole course before it returns to the outer for loop. So, it just repeats one character the amount of times equal to the length. Instead of having another for loop, just add a simple counter for j like j++ inside your outer for loop and use that value with the i value.
To the original poster, consider this:
If you know the length of the original string, you therefore know the offset of that last position within the original string.
Iterate through the original string in reverse order, appending the current position's value to a new string. The new string would be the reverse of the original.
Aydin's example is essentially correct. Here's my very similar version, with comments:
function reverseString(inputString) {
// create a new empty string
var newString = "";
// iterate through the characters of the string in reverse order,
// appending to the new string
for (var i = inputString.length - 1; i >= 0; i--) {
newString += inputString[i];
}
return newString;
}
console.log(reverseString('bootcamp'));
Here is my js:-
function recPerm(rest, soFar) {
var next;
var remaining;
var output=[];
if (rest === '') {
console.log(soFar); //outputting strings..and this works
output.push(soFar);
} else {
for (var i = 0; i < rest.length; i++) {
remaining = rest.substr(0,i) + rest.substr(i+1,rest.length-1);
next = soFar + rest[i];
recPerm(remaining, next);
}
}
return output; //returns an empty array in the end
}
var out=recPerm('abc','');
console.log(out); //prints empty array
Recursively, I am trying to print permutations of an input string. I am passing the input string and a blank string which recursively then calls this function with remaining string and next individual char in string to be considered. Inside base case, I am succesfully able to log individual strings . But somehow its not saving it in my array towards the end. Is there something i am missing out in my JS?
Your problem resides on the output variable, that is private to the recPerm function and when you recursively call recPerm, of course, it will be recreated... I suggest You to pass that variable as parameter:
function recPerm(rest, soFar, output) {
var next;
var remaining;
output = Array.isArray(output) ? output : [];
if(rest === '') {
output.push(soFar);
} else {
for (var i = 0; i < rest.length; i++) {
remaining = rest.substr(0,i) + rest.substr(i+1,rest.length-1);
next = soFar + rest[i];
recPerm(remaining, next, output);
}
}
return output; //returns an empty array in the end
}
var out=recPerm('abc','');
console.log(out);
Given string in the form:
'"abc",ab(),c(d(),e()),f(g(),zyx),h(123)'
How can I split it to get the below array format:
abc
ab()
c(d(),e())
f(g(),zyx)
h(123)
I have tried normal javascript split, however it doesn't work as desired. Trying Regular Expression but not yet successful.
You can keep track of the parentheses, and add those expressions when the left and right parens equalize.
For example-
function splitNoParen(s){
var left= 0, right= 0, A= [],
M= s.match(/([^()]+)|([()])/g), L= M.length, next, str= '';
for(var i= 0; i<L; i++){
next= M[i];
if(next=== '(')++left;
else if(next=== ')')++right;
if(left!== 0){
str+= next;
if(left=== right){
A[A.length-1]+=str;
left= right= 0;
str= '';
}
}
else A=A.concat(next.match(/([^,]+)/g));
}
return A;
}
var s1= '"abc",ab(),c(d(),e()),f(g(),zyx),h(123)';
splitNoParen(s1).join('\n');
/* returned value: (String)
"abc"
ab()
c(d(),e())
f(g(),zyx)
h(123)
*/
This might be not the best or more refined solution, and also maybe won't fit every single possibility, but based on your example it works:
var data = '"abc",ab(),c(d(),e()),f(g(),zyx),h(123)';
// Create a preResult splitting the commas.
var preResult = data.replace(/"/g, '').split(',');
// Create an empty result.
var result = [];
for (var i = 0; i < preResult.length; i++) {
// Check on every preResult if the number of parentheses match.
// Opening ones...
var opening = preResult[i].match(/\(/g) || 0;
// Closing ones...
var closing = preResult[i].match(/\)/g) || 0;
if (opening != 0 &&
closing != 0 &&
opening.length != closing.length) {
// If the current item contains a different number of opening
// and closing parentheses, merge it with the next adding a
// comma in between.
result.push(preResult[i] + ',' + preResult[i + 1]);
i++;
} else {
// Leave it as it is.
result.push(preResult[i]);
}
}
Demo
For future reference, here's another approach to top-level splitting, using string.replace as a control flow operator:
function psplit(s) {
var depth = 0, seg = 0, rv = [];
s.replace(/[^(),]*([)]*)([(]*)(,)?/g,
function (m, cls, opn, com, off, s) {
depth += opn.length - cls.length;
var newseg = off + m.length;
if (!depth && com) {
rv.push(s.substring(seg, newseg - 1));
seg = newseg;
}
return m;
});
rv.push(s.substring(seg));
return rv;
}
console.log(psplit('abc,ab(),c(d(),e()),f(g(),zyx),h(123)'))
["abc", "ab()", "c(d(),e())", "f(g(),zyx)", "h(123)"]
Getting it to handle quotes as well would not be too complicated, but at some point you need to decide to use a real parser such as jison, and I suspect that would be the point. In any event, there's not enough detail in the question to know what the desired handling of double quotes is.
You can't use .split for this, but instead you'll have to write a small parser like this:
function splitNoParen(s){
let results = [];
let next;
let str = '';
let left = 0, right = 0;
function keepResult() {
results.push(str);
str = '';
}
for(var i = 0; i<s.length; i++) {
switch(s[i]) {
case ',':
if((left === right)) {
keepResult();
left = right = 0;
} else {
str += s[i];
}
break;
case '(':
left++;
str += s[i];
break;
case ')':
right++;
str += s[i];
break;
default:
str += s[i];
}
}
keepResult();
return results;
}
var s1= '"abc",ab(),c(d(),e()),f(g(),zyx),h(123)';
console.log(splitNoParen(s1).join('\n'));
var s2='cats,(my-foo)-bar,baz';
console.log(splitNoParen(s2).join('\n'));
Had a similar issue and existing solutions were hard to generalize. So here's another parser that's a bit more readable and easier to extend to your personal needs. It'll also work with curly braces, brackets, normal braces, and strings of any type. License is MIT.
/**
* This function takes an input string and splits it by the given token, but only if the token is not inside
* braces of any kind, or a string.
* #param {string} input The string to split.
* #param {string} split_by Must be a single character.
* #returns {string[]} An array of split parts without the split_by character.
*/
export function parse_split(input:string, split_by:string = ",") : string[]
{
// Javascript has 3 types of strings
const STRING_TYPES = ["'","`","\""] as const;
// Some symbols can be nested, like braces, and must be counted
const state = {"{":0,"[":0,"(":0};
// Some cannot be nested, like a string, and just flip a flag.
// Additionally, once the string flag has been flipped, it can only be unflipped
// by the same token.
let string_state : (typeof STRING_TYPES)[number] | undefined = undefined
// Nestable symbols come in sets, usually in pairs.
// These sets increase or decrease the state, depending on the symbol.
const pairs : Record<string,[keyof typeof state,number]> = {
"{":["{",1],
"}":["{",-1],
"[":["[",1],
"]":["[",-1],
"(":["(",1],
")":["(",-1]
}
let start = 0;
let results = [];
let length = input.length;
for(let i = 0; i < length; ++i)
{
let char = input[i];
// Backslash escapes the next character. We directly skip 2 characters by incrementing i one extra time.
if(char === "\\")
{
i++;
continue;
}
// If the symbol exists in the single/not nested state object, flip the corresponding state flag.
if(char == string_state)
{
string_state = undefined;
console.log("Closed string ", string_state);
}
// if it's not in a string, but it's a string opener, remember the string type in string_state.
else if(string_state === undefined && STRING_TYPES.includes(char as typeof STRING_TYPES[number]))
{
string_state = char as typeof STRING_TYPES[number];
}
// If it's not in a string, and if it's a paired symbol, increase or decrease the state based on our "pairs" constant.
else if(string_state === undefined && (char in pairs) )
{
let [key,value] = pairs[char];
state[key] += value;
}
// If it's our split symbol...
else if(char === split_by)
{
// ... check whether any flags are active ...
if(Object.entries(state).every(([k,v])=>v == 0) && (string_state === undefined))
{
// ... if not, then this is a valid split.
results.push(input.substring(start,i))
start = i+1;
}
}
}
// Add the last segment if the string didn't end in the split_by symbol, otherwise add an empty string
if(start < input.length)
{
results.push(input.substring(start,input.length))
}
else
results.push("");
return results;
}
With this regex, it makes the job:
const regex = /,(?![^(]*\))/g;
const str = '"abc",ab(),c(d(),e()),f(g(),zyx),h(123)';
const result = str.split(regex);
console.log(result);
Javascript
var str='"abc",ab(),c(d(),e()),f(g(),zyx),h(123)'
str.split('"').toString().split(',').filter(Boolean);
this should work
if this type character '這' = NonEnglish each will take up 2 word space, and English will take up 1 word space, Max length limit is 10 word space; How to get the first 10 space.
for below example how to get the result This這 is?
I'm trying to use for loop from first word but I don't know how to get each word in string...
string = "This這 is是 English中文 …";
var NonEnglish = "[^\u0000-\u0080]+",
Pattern = new RegExp(NonEnglish),
MaxLength = 10,
Ratio = 2;
If you mean you want to get that part of the string where it's length has reached 10, here's the answer:
var string = "This這 is是 English中文 …";
function check(string){
// Length of A-Za-z characters is 1, and other characters which OP wants is 2
var length = i = 0, len = string.length;
// you can iterate over strings just as like arrays
for(;i < len; i++){
// if the character is what the OP wants, add 2, else 1
length += /\u0000-\u0080/.test(string[i]) ? 2 : 1;
// if length is >= 10, come out of loop
if(length >= 10) break;
}
// return string from the first letter till the index where we aborted the for loop
return string.substr(0, i);
}
alert(check(string));
Live Demo
EDIT 1:
Replaced .match with .test. The former returns a whole array while the latter simply returns true or false.
Improved RegEx. Since we are checking only one character, no need for ^ and + that were before.
Replaced len with string.length. Here's why.
I'd suggest something along the following lines (assuming that you're trying to break the string up into snippets that are <= 10 bytes in length):
string = "This這 is是 English中文 …";
function byteCount(text) {
//get the number of bytes consumed by a string
return encodeURI(text).split(/%..|./).length - 1;
}
function tokenize(text, targetLen) {
//break a string up into snippets that are <= to our target length
var result = [];
var pos = 0;
var current = "";
while (pos < text.length) {
var next = current + text.charAt(pos);
if (byteCount(next) > targetLen) {
result.push(current);
current = "";
pos--;
}
else if (byteCount(next) == targetLen) {
result.push(next);
current = "";
}
else {
current = next;
}
pos++;
}
if (current != "") {
result.push(current);
}
return result;
};
console.log(tokenize(string, 10));
http://jsfiddle.net/5pc6L/