i was wondering if there is a way to get an array with minimum and maximum values get by another array, or something like this:
var numbers = ['10','15','20','25','30','35','40','45','50'];
var getnumbers = function(min,max){
//return a result that is push to another array, in this case "results"
};
getnumbers(10,30);
console.log(results);
the output should give me something like 10 - 15 - 20 - 25 - 30
A slightly different approach, with a customized callback function for filtering.
function filterNumbers(min, max) {
return function (a) { return a >= min && a <= max; };
}
var numbers = ['10', '15', '20', '25', '30', '35', '40', '45', '50'],
result = numbers.filter(filterNumbers(10, 30));
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You can do something like: numbers.filter(function (value) { return value >= 10 && value <= 30 });
And if you really want the output to be N1 - N2 - N3 ... - NN, just do numbers.filter(function (value) { return value >= 10 && value <= 30 }).join(' - ');
try this
var numbers = ['10','15','20','25','30','35','40','45','50'];
var output = "";
var getnumbers = function(min,max){
for (var i = 0; i < numbers.length; i++){
if(numbers[i] >= min && numbers[i] <= max){
output += numbers[i] + "-";
}
}
};
getnumbers(10,30);
console.log(output);
JavaScript has inbuilt functions to solve this issue.
let numbers = ['10','15','20','25','30','35','40','45','50'];
// Get all elements between '10' and '30'
let result = numbers.splice(numbers.indexOf('10'),numbers.indexOf('30') + 1);
console.log(result);
// If you want the answer to literally be '10-15-20-25-30'
let resultString = "";
for(const i in result){
resultString.concat(`${result[i]}-`)
}
console.log(resultString);
Related
I tried to use a recursive function to reverse a number it works but for one call only it's because of scoping i guess but i don't know how to fix it
let num;
let reversed='';
let result;
function reverseNum(n){
for(let i =0; i<n; i++){
num = n%10; // get the last digit e.g 352 %10 = 2
reversed+= num
result = parseInt(n / 10); // remove last digit e.g. parseInt(352/10) = 35
reverseNum(result);
if(result ===0){
break;
}
}
return reversed;
}
You need the num, reversed, and result variables to be created anew each time the function is called externally. Here's one simple tweak, by defining the recursive function inside the top reverseNum function:
function reverseNum(n) {
let num;
let reversed = '';
let result;
const recurse = (n) => {
for (let i = 0; i < n; i++) {
num = n % 10; // get the last digit e.g 352 %10 = 2
reversed += num
result = parseInt(n / 10); // remove last digit e.g. parseInt(352/10) = 35
recurse(result);
if (result === 0) {
break;
}
}
return reversed;
};
return recurse(n);
}
console.log(reverseNum(1234));
console.log(reverseNum(1234));
But a more elegant method would be:
function reverseNum(n, str = String(n)) {
const thisDigit = str[str.length - 1];
const recursiveResult = str.length === 1 ? '' : reverseNum(str.slice(0, str.length - 1));
return Number(thisDigit + recursiveResult);
}
console.log(reverseNum(1234));
console.log(reverseNum(1234));
function reverse(number){
let index = 0 ;
let reversed = '';
let max = `${number}`.toString().length-1;
while(index <= max ){
reversed += `${number}`.charAt(max-index)
index ++;
}
return reversed;
}
console.log(reverse(546))
CertainPerformance has explained why your code wasn't working.
Here is another implementation, one I find reasonably simple:
const reverseNum = (n) =>
n < 10
? String(n)
: String (n % 10) + reverseNum (Math .floor (n / 10))
console .log (reverseNum (8675309))
Note that this returns a String rather than a Number. If we wanted to, we could make this a private function and make a public function one which called this and converted the result back into a number. But that would have the weird effect that reversing, say, 1000 would yield 1, since 0001 is simplified to 1. And that would mean that when you reverse again, you don't get anything like your original value. So I choose to keep with a String.
Of course if we're going to do String reversal, perhaps we're better off just using a String reversal function in the first place:
const reverseStr = (s) =>
s.length == 0
? ''
: reverseStr (s .slice (1)) + s [0]
const reverseNum = (n) =>
reverseStr (String(n))
console .log (reverseNum (8675309))
Or if we weren't interested in doing this recursively, we could just write the more common string reversal function:
const reverseStr = (s) =>
s .split ('') .reverse () .join ('')
const reverseNum = (n) =>
reverseStr (String (n))
console .log (reverseNum (8675309))
Given Problem:
Write a function called "sumDigits".
Given a number, "sumDigits" returns the sum of all its digits.
var output = sumDigits(1148);
console.log(output); // --> 14
If the number is negative, the first digit should count as negative.
var output = sumDigits(-316);
console.log(output); // --> 4
My code:
function sumDigits(num) {
return num.toString().split("").reduce(function(a, b){
return parseInt(a) + parseInt(b);
});
}
My code solves the problem for positive integers. Any hints on how should I go about solving the problem for negative integers? Please and thanks.
Edit: And what if the given number is 0? Is it acceptable to add an if statement to return 0 in such cases?
Check to see if the first character is a -. If so, b is your first numeral and should be negative:
function sumDigits(num) {
return num.toString().split("").reduce(function(a, b){
if (a == '-') {
return -parseInt(b);
} else {
return parseInt(a) + parseInt(b);
}
});
}
You could use String#match instead of String#split for a new array.
function sumDigits(num) {
return num.toString().match(/-?\d/g).reduce(function(a, b) {
return +a + +b;
});
}
console.log(sumDigits(1148)); // 14
console.log(sumDigits(-316)); // 4
Somebody who is looking for a solution without reduce functions etc. can take this approach.
function sumDigits(num) {
var val = 0, remainder = 0;
var offset = false;
if (num <0) {
offset = true;
num = num * -1;
}
while (num) {
remainder = num % 10;
val += remainder;
num = (num - remainder) / 10;
}
if (offset) {
val -= 2 * remainder;//If the number was negative, subtract last
//left digit twice
}
return val;
}
var output = sumDigits(-348);
console.log(output);
output = sumDigits(348);
console.log(output);
output = sumDigits(1);
console.log(output);
//Maybe this help: // consider if num is negative:
function sumDigits(num){
let negativeNum = false;
if(num < 0){
num = Math.abs(num);
negativeNum = true;
}
let sum = 0;
let stringNum = num.toString()
for (let i = 0; i < stringNum.length; i++){
sum += Number(stringNum[i]);
}
if(negativeNum){
return sum - (Number(stringNum[0]) * 2);
// stringNum[0] has the "-" sign so deduct twice since we added once
} else {
return sum;
}
}
I'm trying to write a function that returns an array of equally chunked up dates and number of days pertaining to those dates. Should there be a remainder of those days they get appended to the array as follow.
Expected outcome:
[{
'startDate' : 20160719 //dates generated from momentjs
'numOfDays': 5
},{
'startDate' : 20160724
'numOfDays': 5
},{
'startDate' : 20160729
'numOfDays': 3
}]
Below is the function I've written in which you can pass in a start date (momentjs), the total number of days (daysToDisplay) and number of days to be divided by (numOfDays).
function buildQueue(startDate, numOfDays, daysToDisplay) {
if (!startDate || !numOfDays || !daysToDisplay) {
throw new Error('All params required!');
}
var num = numOfDays > daysToDisplay ? daysToDisplay : numOfDays;
var div = Math.floor(daysToDisplay / num);
var count = daysToDisplay;
var rem = daysToDisplay % num;
var lastItem;
var i;
var arr = [];
for (i = 0; i <= daysToDisplay; i += num) {
arr.push({
startDate: moment(startDate, 'YYYYMMDD').add(i, 'days').format('YYYYMMDD'),
numOfDays: numOfDays,
count: i
})
if (rem === count) {
break;
}
count -= num;
}
if (count > 0) {
lastItem = arr[arr.length - 1];
var leftover = daysToDisplay - lastItem.count;
arr.push({
startDate: moment(lastItem.startDate, 'YYYYMMDD').add(num, 'days').format('YYYYMMDD'),
numOfDays: rem,
count: leftover + lastItem.count
});
}
return arr;
}
A working example is here (https://jsfiddle.net/zv5ghqpa/1/). The code appears to work in scenarios where daysToDisplay is dividable by more than 2.
When daysToDisplay is only dividable by one, we get an additional item in the returned array basically due to the zero index in the for loop. The expected outcome if I call buildQueue('20160719', 5, 8) should be:
[{
'startDate': 20160719
'numOfDays': 5
}, {
'startDate': 20160724
'numOfDays': 3
}]
Instead its returning:
[{
'startDate': 20160719
'numOfDays': 5
},{
'startDate': 20160724
'numOfDays': 5
}, {
'startDate': 20160729
'numOfDays': 3
}]
I hope i've given enough info... this is really doing my head in.
Thanks in advance!
I think this is code you're looking for:
function buildQueue(startDate, numOfDays, daysToDisplay) {
if (!startDate || !numOfDays || !daysToDisplay) {
throw new Error('All params required!');
}
var num = numOfDays > daysToDisplay ? daysToDisplay : numOfDays;
var div = Math.floor(daysToDisplay / num);
var count = daysToDisplay;
var rem = daysToDisplay % num;
var n = 0;
var i;
var arr = [];
for (i = 0; i <= daysToDisplay; i += num) {
arr.push({
startDate: moment(startDate, 'YYYYMMDD').add(i, 'days').format('YYYYMMDD'),
numOfDays: daysToDisplay % num,
count: i
})
console.log(rem + ' ' + count);
if (rem === count) {
count = 0;
break;
}
count -= num;
}
if (count > 0) {
var leftover = daysToDisplay - arr[arr.length - 1].count;
arr.push({
startDate: moment(arr[arr.length - 1].startDate, 'YYYYMMDD').add(num, 'days').format('YYYYMMDD'),
numOfDays: daysToDisplay % num,
count: leftover + arr[arr.length - 1].count
});
}
return arr;
}
//console.log(buildQueue(moment(), 80, 100));
console.log(buildQueue(moment(), 5, 8));
//console.log(buildQueue(moment(), 15, 100));
//console.log(buildQueue(moment(), 30, 100));
//console.log(buildQueue(moment(), 45, 100));
I think the 'Expected outcome' was correct before you edited the question. I also note the sample code produced a count property that you don't want in the output.
Perhaps this code does what you want?
function buildQueue(startDate, numOfDays, daysToDisplay) {
var arr = []
while (daysToDisplay > 0) {
arr.push({
startDate: moment(startDate, 'YYYYMMDD')
.add(numOfDays * arr.length, 'days')
.format('YYYYMMDD'),
numDays: Math.min(numOfDays, daysToDisplay)
})
daysToDisplay -= numOfDays
}
return arr
}
Lets say you have input Array=[1,2,3,5,7,9,10,11,12,15]
The output should be 1-3,5,7,9-12,15
Im looking for feedback on my attempt and other possible solutions.
Heres my attempt in javascript:
var min = 0;
var max = -1;
function summarize(array) {
var sumString = "";
var prevVal = -1;
array.forEach(function(currVal, index) {
if (index > 0) {
prevVal = array[index - 1];
}
if (index === 0) {
min = currVal;
max = currVal;
} else if (currVal - prevVal === 1) {
max = currVal;
} else if (min !== max && max !== -1) {
sumString += min + "-" + max + (index < array.length - 1 ? "," : "");
min = currVal;
max = -1;
} else {
sumString += min + (index < array.length - 1 ? "," : "");
}
if (index === array.length - 1) {
if (max === -1) {
sumString += "," + min;
} else {
sumString += min + "-" + max;
}
}
});
return sumString;
}
Here is a slightly shorter implementation:
var i = 0, prev, arr = [1,2,3,5,7,9,10,11,12,15], out = [];
for(i=0; i<arr.length; prev = arr[i], i++) {
// if the current number is not prev+1, append it to out
// Note that we are adding it as a string, to ensure that
// subsequent calls to `split()` (see else part) works
if(prev !== arr[i] - 1) out.push(String(arr[i]));
// if the current number is prev+1, modify the last value
// in out to reflect it in the RHS of - (hyphen)
else out[out.length - 1] = [out[out.length - 1].split('-')[0], String(arr[i])].join('-');
}
// out => ["1-3", "5", "7", "9-12", "15"]
Another possible solution for positive numbers in ascending order. It features Array.prototype.reduce.
var array = [1, 2, 3, 5, 7, 9, 10, 11, 12, 15, 23, 24],
result = [];
array.reduce(function (r, a) {
result.push(r + 1 - a ? String(a) : result.pop().split('-')[0] + '-' + String(a));
return a;
}, array[0]);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Another possible solution :
var points = [1,2,3,5,6,31,7,9,10,11,12,15];
points.sort(function(a, b){return a-b}); //sort array in asc
var resultArr=[];
var max; var min;
for(i=0;i<points.length;i++) //loop
{
if(i==0)
{
min=points[i]; //lowest number in arr
max=points[i]+1; //assign next value
}
else
{
if(max==points[i]) //if value matches continue
max=points[i]+1;
else //next value is not an incremental one so push it to result arr
{
max=max-1;
resultArr.push(min+(min!=max? "-"+ max :""));
min=points[i];
max=points[i]+1;
}
if(i==points.length-1) //last element of the arr so push it to result arr
{
max=max-1;
resultArr.push(min+(min!=max? "-"+ max :""));
}
}
}
alert(resultArr);
First step uses dashes to separate sequential numbers and commas if they aren't. Second step replaces -#- with -.
var X = [1,2,3,5,7,9,10,11,12,15];
var S = '' + X[0];
for (var i = 1; i < X.length; i++) {
S += (X[i] == X[i - 1] + 1)? '-': ',';
S += X[i];
}
while (/-[0-9]+-/.test(S))
S = S.replace(/-[0-9]+-/g, '-');
alert(S);
For a sequence like 1,2,5,6 will output 1-2,5-6 which might not be what you're looking for, so an optional third step would be to replace #-#+1 with #,#+1, i.e. restore the comma:
for (var i = 1; i < X.length; i++)
S = S.replace(X[i - 1] + '-' + X[i], X[i - 1] + ',' + X[i]);
I ran into this problem recently, after some reflection, I noticed 3 different transformations: (1) Group consecutive numbers; (2) Transform groups into strings representing the ranges; (3) Join range strings on comma.
function summarizeRange(items) {
const sorted = items.slice(0).sort((a, b) => a - b);
return sorted
.slice(1)
.reduce((range, item) => {
const rangedIndex = range.reduce((ranged, rangedCollection, index) =>
rangedCollection.indexOf(item - 1) > -1 ? index : ranged,
-1
);
if (rangedIndex > -1) {
range[rangedIndex] = range[rangedIndex].concat(item);
return range;
}
return range.concat([
[item]
]);
}, [
[sorted[0]]
])
.map(range => range.length > 1 ?
'' + range[0] + '-' + range[range.length - 1] :
'' + range[0]
)
.join(',');
}
console.log(summarizeRange([0,3,2,6,19,20,22,21,1]));
For example. I want to print numbers from 1 to 20
but I want print 1 as 01 , 2 as 02 and so on ..
formatNumber = function( num )
{
if ( num < 10 )
{
return "0" + num;
}
else
{
return "" + num;
}
}
Here's a generic 'zeroPad' function for you:
function zeroPad(nr,base){
base = base || 10;
var len = (String(base).length - String(nr).length)+1;
return len > 0 ? new Array(len).join('0')+nr : nr;
}
//usage
zeroPad(5); //=> "05"
zeroPad(50,1000); //=> "0050"
zeroPad(50); //=> "50"
or as Number Extension:
Number.prototype.zeroPad = Number.prototype.zeroPad ||
function(base){
base = base || 10;
var len = (String(base).length - String(this).length)+1;
return len > 0 ? new Array(len).join('0')+this : this;
};
//usage
(5).zeroPad(); //=> "05"
(50).zeroPad(1000); //=> "0050"
(50).zeroPad(); //=> "50"
Let's abuse the ternary operator:
for(var n = 1; n <= 20; n++) {
console.log((n < 10 ? '0' : '') + n)
}
Here is shorter version:
leadingZero = function(num){
return (num < 10) ? "0"+num : num;
}
Use String.prototype.padStart:
`${num}`.padStart(2, '0');
From MDN:
The padStart() method pads the current string with another string (repeated, if needed) so that the resulting string reaches the given length. The padding is applied from the start (left) of the current string.
padStart is only defined on strings—not numbers—so you need to cast the number to string (num.toString(); or more idiomatically `${num}`) before you call padStart. The first parameter is the minimum length of the outcome string so if you numbers reach the hundreds do `${num}`.padStart(3, '0').
// Create an array of the numbers 1 through 20.
const arr = Array.from({ length: 20 }, (_, i) => i + 1);
arr.forEach(i => {
// Pad each one digit number with a leading zero.
console.log(`${i}`.padStart(2, '0'));
})