【问题标题】:Creating a sequence of numbers from a singular number从单个数字创建数字序列
【发布时间】:2023-01-24 09:40:05
【问题描述】:

我需要为分页链接创建一个数字序列,这个序列的长度需要 7 个数字,在给定数字之前开始 3 个数字,在给定数字之后结束 3 个数字,所以如果当前页面是 17,那么序列将是,

14、15、16、17、18、19、20

我用下面的代码工作,

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

但是这段代码需要我发送起点和终点,如果我在当前页面 <=3 时执行此操作,我将输入负数以获得序列,而实际上我想要的是这样的序列,

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

所以它的长度仍然是 7 个数字,但是因为它不能做 3 个前面的数字,因为它会从 0 或更低的位置开始,所以它只做了 7 个序号。

在 Javascript 中有没有一种方法可以解决这些问题,而不需要一大堆 If/Else 条件语句?

【问题讨论】:

  • 如果 < 3,则重置为 1

标签: javascript math numbers sequential


【解决方案1】:

只需使用您喜欢的任何逻辑从页码(下例中的x)导出开始和停止。就像是:

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(", "))
}

【讨论】:

    【解决方案2】:

    一个单独的 if-else 语句应该不会那么糟糕。这是一个函数getPages,您可以在其中传入当前页码,它会根据您的描述生成一系列页面。

    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))

    【讨论】:

    • 作为旁注,如果您只需要序列中的 7 个数字,那么直接键入它比使用像 Array.from(...) 这样的复杂结构更具可读性。
    【解决方案3】:

    这是一个使用三元运算符使其保持一行的示例,但如果您觉得它更具可读性,则可以使用简单的 if/else

    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))

    【讨论】:

      【解决方案4】:

      我可能走得有点远,但话虽这么说,一种方法如下,代码中有解释性 cmets:

      // 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

      参考:

      【讨论】:

        【解决方案5】:

        我认为这是最简单的方法,它不会使用从 1 开始的任何小于 4 的数字然后它会在 4 之后增加以使用 3nums before 和 3 after

        尝试输入任意数字并点击生成

        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>

        【讨论】:

          【解决方案6】:

          这个问题可以用几个简单的技巧来解决。

          考虑到 n 是当前数字,方法如下所示:

          1. 使用字符串序列1…7将其转化为数组并进行迭代
          2. 如果n<4,不要修改序列1…7,否则将每个元素扩大n-4

            所有这些都可以在这个小代码 sn-p 中完成

            n = 6
            pgn = [..."1234567"].map(x=>n<4?+x:x-4+n)
            console.log(pgn)

            可读性的扩展版本:

            n = 6
            pgn = [..."1234567"].map(
               x=> n<4
                ? +x // + sign to convert str to num
                : x-4+n
            )
            console.log(pgn)
            

          【讨论】:

            猜你喜欢
            • 2015-08-25
            • 1970-01-01
            • 1970-01-01
            • 2021-11-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-19
            相关资源
            最近更新 更多