Home > front end >  Creating a sequence of numbers from a singular number
Creating a sequence of numbers from a singular number

Time:01-24

I need to create a sequence of numbers for pagination links, this sequence needs to be 7 numbers in length and start 3 numbers before the given number and end 3 numbers after the given number so if the current page was 17 the sequence would be,

14, 15, 16, 17, 18, 19, 20

I have this working with the following code,

const range = (start, stop) => Array.from({ length: (stop - start)}, (_, i) => start (i*1));

But this code requires me to send the start and stop points, if I do this when the current page is <=3 I drop into minus numbers to get the sequence, when in reality would I would want is a sequence like,

3, 4, 5, 6, 7, 8, 9

so it's still 7 numbers in length, but because it couldn't do 3 preceeding number becaue it would start at 0 or lower it just did 7 proceeding numbers instead.

Is there a way in Jascript to work this stuff out, without a whole load of If/Else conditionals?

CodePudding user response:

Just derive start & stop from the page number (x in the example below) using whatever logic you would like. Something like:

const range = (x) => {
  const start = Math.max(1,x-3);
  const stop = start   7;
  return Array.from({ length: (stop - start)}, (_, i) => start   i);
}

for(let i=1;i<20;i  ){
  console.log(i," -->", range(i).join(", "))
}

CodePudding user response:

A single if-else statement shouldn't be that bad. Here's a function getPages where you pass in the current page number and it generates a range of pages according to your description.

function getPages(n) {
    if (n > 3) {
        return [n - 3, n - 2, n - 1, n, n   1, n   2, n   3];
    } else {
        return [n, n   1, n   2, n   3, n   4, n   5, n   6];
    }
}

console.log(getPages(1))
console.log(getPages(3))
console.log(getPages(4))
console.log(getPages(17))

CodePudding user response:

Here's an example using the ternary operator to keep it one line, but you could use a simple if/else if you find it more readable

let pageNumber = 17;

const range = (pageNumber) => Array.from({length: 7}, (_, i) => pageNumber < 4 ? i   1 : i   (pageNumber - 3))

console.log(range(pageNumber))

pageNumber = 3

console.log(range(pageNumber))

CodePudding user response:

I may have gone a bit far but, that being said, one approach is as below with explanatory comments in the code:

// a simple function to create new elements, with Object.assign() to set their properties:
const create = (tag, props) => Object.assign(document.createElement(tag), props),
  // an arrow function that takes two numbers:
  // startNumber: the number that should normally be in the centrepoint of the range,
  // and the size of the range itself, these both have default values (adjust as required):
  generateRange = (startNumber = 5, range = 7) => {
    // here we find the minimum value, by taking the supplied (or default) startNumber
    // and subtracting the floored result of the range divided by 2:
    let minValue = startNumber - Math.floor(range / 2);
    // if that minimum value is less than 1:
    if (minValue < 1) {
      //we set the minimum value to 1:
      minValue = 1;
    }
    // creating the Array of numbers:
    let baseRange = Array.from({
      // setting the length of the created Array:
      length: 7
    }).map(
      // passing in the index of the current array-element,
      // and adding the current index to the supplied minValue:
      (_, i) => i   minValue);
    // returning the created range:
    return baseRange;
  }

// iterating over the collection of <li> elements in the document,
// using NodeList.prototype.forEach():
document.querySelectorAll('li').forEach(
  // passing the current <li> element, and the index of that
  // element, to the function body:
  (el, i) => {
    // adding 1 to the zero-based index (this is - admittedly -
    // entirely unnecessary, but I did it anyway):
    let rangeStartValue = i   1;
    
    // appending a created <span> to the current <li>
    el.append(create('span', {
      // setting the textContent of that <span>:
      textContent: rangeStartValue
    }));

    // creating a range of numbers, passing the rangeStartValue,
    // and iterating over the resulting Array using Array.prototype.forEach():
    generateRange(rangeStartValue).forEach(
      // passing the current array-element (an integer):
      (rangeValue) => {
        // for each element we append a created <a> element:
        el.append(
          create('a', {
            // with its textContent set to the current array-element value:
            textContent: rangeValue,
            // setting the href property of the element to a fragment identifier
            // followed by the current array-element value:
            href: `#${rangeValue}`,
            // if the current rangeValue is exactly equal to the rangeStartValue,
            // we add the class-name of 'current', otherwise we add an empty string
            // (which results in the 'class' attribute being present, but containing
            // no class-names:
            className: rangeValue === rangeStartValue ? 'current' : 'other'
          })
        );
      });
  });
li {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
  gap: 0.5rem;
  margin-block: 0.25em;
}

span {
  flex-basis: 100%;
}

span::before {
  content: 'Starting at ';
}

span::after {
  content: ': ';
}

a {
  border: 1px solid currentColor;
  color: rebeccapurple;
  flex-basis: 3em;
  flex-grow: 1;
  padding: 0.5rem;
  text-align: center;
}

.current {
  background-color: skyblue;
  color: white;
}
<ol>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ol>

JS Fiddle demo.

References:

CodePudding user response:

i think this is the most easy way, it will not use start from 1 for any number less than 4 then it will increase after 4 to use 3nums before and 3 after

try to enter any number and click generate

let btn = document.querySelector('input[type="button"]')
let rslt = document.querySelector('div#result')
let elm = document.querySelector('input[type="text"]')
let before= [], after = []
const getSerial = (n) => {
    before = []
    after = []
    let beforeNum = parseInt(n)-4
    let afterNum = parseInt(n)
    for(let i=1;i<4;i  ){
      before.push(beforeNum i)
      after.push(afterNum i)
    }
}
btn.addEventListener('click', () => {
  let num = parseInt(elm.value)
    while( num <= 3) {
      num = 4
    }
  getSerial(parseInt(num))
  let result = before.concat(parseInt(num)).concat(after)
  rslt.innerHTML = result.toString().replaceAll(',',' ')
})
<input type="text" />
<input type="button" value="generate" />

<div id="result"></div>

  • Related