带省略号的分页算法

Sar*_*air 4 javascript algorithm pagination reactjs

作为我日常工作的一部分,我的任务是在我的反应应用程序中实现分页。我完成了 UI 和状态管理,但陷入了分页算法。我参考了下面列出的许多标准算法

  1. https://gist.github.com/kottenator/9d936eb3e4e3c3e02598
  2. https://flaviusmatis.github.io/simplePagination.js

问题是我们的算法略有修改。我所做的是使用这里提到的算法 - https://gist.github.com/kottenator/9d936eb3e4e3c3e02598并实现了具有不同 UI 状态的基本分页组件。( If array[i] === selectedPageFromProps, then highlight that page with different colour)

该算法的作用是将 selectedPage 和totalNumberOfPages 作为参数,并返回带有省略号的所有页面的数组(如果有更多页面)

函数分页(selectedPage,totalPages){返回带有省略号的arrayOfPageNumbers(如果需要)}

该算法应根据设备返回不同的值 - 在移动设备中,我们最多显示 4 个数字,在桌面设备中,我们最多显示 7 个页面。

下面提到该算法的不同返回值。

In Mobile - Max number of pages to be displayed is 4
*****************************************************

pagination(1,4) : 1,2,3,4
pagination(2,4) : 1,2,3,4
pagination(3,4) : 1,2,3,4
pagination(4,4) : 1,2,3,4

If totalPages > 4

pagination(1,99) : 1,2,3,...,99
pagination(2,99) : 1,2,3,...,99
pagination(3,99) : 1,...,3,...,99
pagination(4,99) : 1,...,4,...,99
pagination(5,99) : 1,...,5,...,99
pagination(97,99) : 1,...,97,...99
pagination(98,99) : 1,...,98,...99
pagination(99,99) : 1,...,98,99

In Desktop/Tablet - Max number of pages to be displayed is 7
************************************************************
pagination(1,7) : 1,2,3,4,5,6,7
pagination(2,7) : 1,2,3,4,5,6,7
pagination(7,7) : 1,2,3,4,5,6,7


If totalPages > 7

pagination(1,99) : 1,2,3,4,5,6,...,99
pagination(2,99) : 1,2,3,4,5,6,...,99
pagination(4,99) : 1,2,3,4,5,6,...,99
pagination(5,99) : 1,...,3,4,5,6,7,...,99
pagination(95,99) : 1,...,93,94,95,96,97,...,99
pagination(96,99) : 1,...,94,95,96,97,98,...,99
pagination(97,99) : 1,...,95,96,97,98,99
pagination(98,99) : 1,...,95,96,97,98,99
pagination(99,99) : 1,...,95,96,97,98,99
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我修改或实现新算法吗?

目前我正在使用下面提到的算法。

function pagination(currentPage, nrOfPages, deltaValue) {
    var delta = deltaValue,
      range = [],
      rangeWithDots = [],
      l;

    range.push(1);

    if (nrOfPages <= 1) {
      return range;
    }

    for (let i = currentPage - delta; i <= currentPage + delta; i++) {
      if (i < nrOfPages && i > 1) {
        range.push(i);
      }
    }
    range.push(nrOfPages);

    for (let i of range) {
      if (l) {
        if (i - l === 2) {
          rangeWithDots.push(l + 1);
        } else if (i - l !== 1) {
          rangeWithDots.push("...");
        }
      }
      rangeWithDots.push(i);
      l = i;
    }

    return rangeWithDots;
  }
Run Code Online (Sandbox Code Playgroud)

Sco*_*yet 5

这是一个版本,它接受一个count参数来说明您想要显示多少页(4对于移动设备,7在您的示例中用于桌面)并返回一个函数,该函数获取页码和总页数,并返回一个包含页码和页数的数组根据需要省略。

\n

更新:我写这篇文章只是为了回答问题。但我最近自己也需要这种行为,并且想要一个真实的ellipsis角色而不是三个点。此版本将“\xe2\x80\xa6”设为默认值,但允许您将其覆盖为默认可选参数。(为了清楚起见,我还添加了一些测试。)

\n

\r\n
\r\n
const {floor, min, max} = Math\nconst range = (lo, hi) => Array .from ({length: hi - lo}, (_, i) => i + lo)\n\nconst pagination = (count, ellipsis = \'\xe2\x80\xa6\') => (page, total) => {\n  const start = max (1, min (page - floor ((count - 3) / 2), total - count + 2))\n  const end = min (total, max (page + floor ((count - 2) / 2), count - 1))\n  return [\n    ... (start > 2 ? [1, ellipsis] : start > 1 ? [1] : []), \n    ... range (start, end + 1), \n    ... (end < total - 1 ? [ellipsis, total] : end < total ? [total] : [])\n  ]\n}\n\nconst tests = [\n  /* Mobile(4), 3 pages */   [4, 1, 3], [4, 2, 3], [4, 3, 3],\n  /* Mobile(4), 4 pages */   [4, 1, 4], [4, 2, 4], [4, 3, 4], [4, 4, 4],\n  /* Mobile(4), 99 pages */  [4, 1, 99], [4, 2, 99], [4, 3, 99], [4, 4, 99], [4, 5, 99], [4, 97, 99], [4, 98, 99], [4, 99, 99],\n  /* Desktop(7), 5 pages */  [7, 1, 5], [7, 2, 5], [7, 3, 5], [7, 4, 5], [7, 5, 5],\n  /* Desktop(7), 7 pages */  [7, 1, 7], [7, 2, 7], [7, 7, 7],\n  /* Desktop(7), 99 pages */ [7, 1, 99], [7, 2, 99], [7, 4, 99], [7, 5, 99], [7, 6, 99], [7, 95, 99], [7, 96, 99], [7, 97, 99], [7, 98, 99], [7, 99, 99],  \n]\n\ntests .forEach (([c, p, t]) => {\n  console .log (`pagination (${c}) (${p}, ${t}) //=> [${pagination (c) (p, t) .join (\', \')}]`)\n})  
Run Code Online (Sandbox Code Playgroud)\r\n
.as-console-wrapper {max-height: 100% !important; top: 0}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

以前的版本:

\n

\r\n
\r\n
const {floor, min, max} = Math\nconst range = (lo, hi) => Array .from ({length: hi - lo}, (_, i) => i + lo)\n\nconst pagination = (count) => (page, total) => {\n  const start = max (1, min (page - floor ((count - 3) / 2), total - count + 2))\n  const end = min (total, max (page + floor ((count - 2) / 2), count - 1))\n  return [\n    ... (start > 2 ? [1, \'...\'] : start > 1 ? [1] : []), \n    ... range (start, end + 1), \n    ... (end < total - 1 ? [\'...\', total] : end < total ? [total] : [])\n  ]\n}\n\nconst tests = [\n  /* Mobile, 4 pages */   [4, 1, 4], [4, 2, 4], [4, 3, 4], [4, 4, 4],\n  /* Mobile, 99 pages */  [4, 1, 99], [4, 2, 99], [4, 3, 99], [4, 4, 99], [4, 5, 99], [4, 97, 99], [4, 98, 99], [4, 99, 99],\n  /* Desktop, 7 pages */  [7, 1, 7], [7, 2, 7], [7, 7, 7],\n  /* Desktop, 99 pages */ [7, 1, 99], [7, 2, 99], [7, 4, 99], [7, 5, 99], [7, 95, 99], [7, 96, 99], [7, 97, 99], [7, 98, 99], [7, 99, 99],  \n]\n\ntests .forEach (([c, p, t]) => {\n  console .log (`pagination (${c}) (${p}, ${t}) //=> [${pagination (c) (p, t)}]`)\n})
Run Code Online (Sandbox Code Playgroud)\r\n
.as-console-wrapper {max-height: 100% !important; top: 0}
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

我们包含一个可重用的range函数,它给出一个整数范围,包括其开头,不包括其结尾。我们可以内联这个函数,因为它只使用一次,但我发现我到处都使用它。

\n

我们的主函数计算包含数字的范围的startend,注意不要超出范围 1 - totalmaxmin的复杂性floor在于处理预期范围超出这些边界的所有可能性。然后它构建一个输出,处理值和省略号的各种组合。start在我们的-范围之前end,开头可以1跟一个省略号,也可以只是一个1,也可以为空。然后在范围之后,我们在最后有类似的行为。

\n

当该范围内应该有偶数个值时,我选择的处理方式与所要求的问题略有不同。这个问题似乎想确保结果在目标值周围对称,即使这意味着遗漏一个。(或者至少这是我对示例的解释。)我选择保留偶数,并在中心数字的右侧添加额外的数字,因为向前导航比向后导航更常见。但这很容易改变为对称行为,通过替换这一行:

\n
  const end = Math .min (total, Math .max (page + floor ((count - 2) / 2), count - 1))\n
Run Code Online (Sandbox Code Playgroud)\n

有了这个变体:

\n
  const end = Math .min (total, Math .max (page + floor ((count - 4 + 2 * (count % 2)) / 2), count - 1))\n
Run Code Online (Sandbox Code Playgroud)\n