Javascript 不使用';不要让一页太大或太小

Javascript 不使用';不要让一页太大或太小,javascript,typescript,algorithm,pagination,Javascript,Typescript,Algorithm,Pagination,我想编写一个分页算法,该算法平均分配每页的元素数,每页指定最小和最大元素数。如果可能的话,我希望在不违反最小规则的情况下,每个页面可以有最大数量的元素 我试着写一段时间自己的版本,但是当我把页面上的元素分配到一个我认为美观的方式时,我就陷入了困境。以下是我的测试代码: describe('paginate()', () => { it('puts everything on one page is less than or equal to maximum', () =>

我想编写一个分页算法,该算法平均分配每页的元素数,每页指定最小和最大元素数。如果可能的话,我希望在不违反最小规则的情况下,每个页面可以有最大数量的元素

我试着写一段时间自己的版本,但是当我把页面上的元素分配到一个我认为美观的方式时,我就陷入了困境。以下是我的测试代码:

  describe('paginate()', () => {
    it('puts everything on one page is less than or equal to maximum', () => {
      expect(paginate([1, 2], 1, 8)).toEqual([[1, 2]]);
      expect(paginate([1, 2], 3, 8)).toEqual([[1, 2]]);
      expect(paginate([1, 2], 1, 2)).toEqual([[1, 2]]);
    });

    it('divides everything evenly if there are no remainders on the max', () => {
      expect(paginate([1, 2, 3, 4, 5, 6], 1, 3)).toEqual([
        [1, 2, 3],
        [4, 5, 6],
      ]);
      expect(paginate([1, 2, 3, 4, 5, 6], 1, 2)).toEqual([
        [1, 2],
        [3, 4],
        [5, 6],
      ]);
    });

    it('merges the last page if there is one left over', () => {
      let outcome = paginate([1, 2, 3, 4, 5, 6, 7], 2, 4);
      expect(outcome).toEqual([
        [1, 2, 3, 4],
        [5, 6, 7],
      ]);
      outcome = paginate([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2, 4);
      console.log('outcome', outcome);
      expect(outcome).toEqual([
        [1, 2, 3, 4],
        [5, 6, 7],
        [8, 9, 10],
      ]); // THIS TEST FAILS
    });

    it('can reduce page sizes if it makes elements evenly distributed', () => {
      let outcome = paginate(_.range(1, 12), 6, 10);
      expect(outcome).toEqual(
        [
          [1, 2, 3, 4, 5, 6],
          [7, 8, 9, 10, 11],
        ],
        JSON.stringify(outcome)
      );
      outcome = paginate(_.range(1, 22), 6, 10);
      expect(outcome).toEqual(
        [
          [1, 2, 3, 4, 5, 6, 7],
          [8, 9, 10, 11, 12, 13, 14],
          [15, 16, 17, 18, 19, 20, 21],
        ],
        JSON.stringify(outcome)
      );
    });
  });
这是我的密码:

import _ from 'lodash';

export const paginate = <T>(content: T[], min: number, max: number): T[][] => {
  const length = content.length;
  for (let i = max; i > min; i--) {
    if (length % i === 0 || length % i >= min) {
      const result = _.chunk(content, i);
      console.log(result);
      return result;
    }
  }
  console.log('end');
  return _.chunk(content, min);
};
输出是
[[1,2,3,4],[5,6,7,8],[9,10]]
而不是我想要的。每次我想到这个问题的解决方案,它就打破了另一个考验。我已经辛苦工作了几个小时了,我被困住了我不知道如何通过所有这些测试。此外,是否有我可能没有想到的边缘案例


我不受这个函数的签名限制,所以如果更改它是有意义的,请随意。例如,我并不完全相信我需要提供一个min值。

我倾向于这样做:

function paginate<T>(arr: T[], maxPerPage: number): T[][] {
    const numPages = Math.ceil(arr.length / maxPerPage);
    const minPerPage = Math.floor(arr.length / numPages);
    const numBigPages = arr.length % numPages;
    console.log(numPages, minPerPage, numBigPages)
    const ret: T[][] = [];
    for (let pageNum = 0, curElem = 0; pageNum < numPages; pageNum++) {
        const numOnThisPage = minPerPage + (pageNum < numBigPages ? 1 : 0);
        ret.push(arr.slice(curElem, curElem + numOnThisPage));
        curElem += numOnThisPage;
    }
    return ret;
}
这看起来像是你想要的,对吗


显然,该算法的精确实现可能会发生变化;如果您想使用lodash或通过纯函数方法生成数组,而不是迭代和使用
push()
,这取决于您自己。但基本概念似乎与你想要的相符。无论如何,希望这能让你继续。祝你好运


是的,这正是我想要的。我想我已经解决了,但通过运行您的算法,我发现我的一个测试(此处未显示)有一个bug。另外,我使用的是递归,效率很低。感谢您花时间回答这个问题
function paginate<T>(arr: T[], maxPerPage: number): T[][] {
    const numPages = Math.ceil(arr.length / maxPerPage);
    const minPerPage = Math.floor(arr.length / numPages);
    const numBigPages = arr.length % numPages;
    console.log(numPages, minPerPage, numBigPages)
    const ret: T[][] = [];
    for (let pageNum = 0, curElem = 0; pageNum < numPages; pageNum++) {
        const numOnThisPage = minPerPage + (pageNum < numBigPages ? 1 : 0);
        ret.push(arr.slice(curElem, curElem + numOnThisPage));
        curElem += numOnThisPage;
    }
    return ret;
}
const range = (n: number) => Array.from({ length: n }, (_, i) => i + 1);

console.log(JSON.stringify(paginate(range(2), 8))); // [[1,2]]
console.log(JSON.stringify(paginate(range(2), 2))); // [[1,2]]
console.log(JSON.stringify(paginate(range(6), 3))); // [[1,2,3],[4,5,6]]
console.log(JSON.stringify(paginate(range(6), 2))); // [[1,2],[3,4],[5,6]]

console.log(JSON.stringify(paginate(range(7), 4))); // [[1,2,3,4],[5,6,7]]
console.log(JSON.stringify(paginate(range(10), 4))); // [[1,2,3,4],[5,6,7],[8,9,10]]

console.log(JSON.stringify(paginate(range(11), 10))); // [[1,2,3,4,5,6],[7,8,9,10,11]]
console.log(JSON.stringify(paginate(range(21), 10)));
// [[1,2,3,4,5,6,7],[8,9,10,11,12,13,14],[15,16,17,18,19,20,21]]