【问题标题】:Pagination Algorithm with ellipsis带省略号的分页算法
【发布时间】:2021-12-08 00:46:36
【问题描述】:

作为我日常工作的一部分,我的任务是在我的 react 应用中实现分页。我完成了 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 作为参数,并返回一个带有省略号的所有页面的数组(如果有更多页面)

function pagination(selectedPage, totalPages) {return arrayOfPageNumbers with Ellipsis(if required)}

算法应根据设备返回不同的值 - 在移动设备中,我们最多显示 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

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

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

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;
  }

【问题讨论】:

  • 有四种情况:无省略号、左侧省略号、右侧省略号、左右省略号。所以代码需要决定适用哪种情况,然后为每种情况生成适当的输出。
  • 我找到的关于堆栈溢出的最佳解释stackoverflow.com/a/56671681/14204424

标签: javascript reactjs algorithm pagination


【解决方案1】:
// Implementation in ES6
function pagination(c, m) {
    var current = c,
        last = m,
        delta = 2,
        left = current - delta,
        right = current + delta + 1,
        range = [],
        rangeWithDots = [],
        l;

    for (let i = 1; i <= last; i++) {
        if (i == 1 || i == last || i >= left && i < right) {
            range.push(i);
        }
    }

    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;
}

/*
Test it:
for (let i = 1, l = 20; i <= l; i++)
    console.log(`Selected page ${i}:`, pagination(i, l));

Expected output:
Selected page 1: [1, 2, 3, "...", 20]
Selected page 2: [1, 2, 3, 4, "...", 20]
Selected page 3: [1, 2, 3, 4, 5, "...", 20]
Selected page 4: [1, 2, 3, 4, 5, 6, "...", 20]
Selected page 5: [1, 2, 3, 4, 5, 6, 7, "...", 20]
Selected page 6: [1, "...", 4, 5, 6, 7, 8, "...", 20]
Selected page 7: [1, "...", 5, 6, 7, 8, 9, "...", 20]
Selected page 8: [1, "...", 6, 7, 8, 9, 10, "...", 20]
Selected page 9: [1, "...", 7, 8, 9, 10, 11, "...", 20]
Selected page 10: [1, "...", 8, 9, 10, 11, 12, "...", 20]
Selected page 11: [1, "...", 9, 10, 11, 12, 13, "...", 20]
Selected page 12: [1, "...", 10, 11, 12, 13, 14, "...", 20]
Selected page 13: [1, "...", 11, 12, 13, 14, 15, "...", 20]
Selected page 14: [1, "...", 12, 13, 14, 15, 16, "...", 20]
Selected page 15: [1, "...", 13, 14, 15, 16, 17, "...", 20]
Selected page 16: [1, "...", 14, 15, 16, 17, 18, 19, 20]
Selected page 17: [1, "...", 15, 16, 17, 18, 19, 20]
Selected page 18: [1, "...", 16, 17, 18, 19, 20]
Selected page 19: [1, "...", 17, 18, 19, 20]
Selected page 20: [1, "...", 18, 19, 20]
*/

我想这就是你要找的东西?

更多详情请访问: https://gist.github.com/kottenator/9d936eb3e4e3c3e02598

【讨论】:

    【解决方案2】:

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

    const {floor, min, max} = Math
    const range = (lo, hi) => Array .from ({length: hi - lo}, (_, i) => i + lo)
    
    const pagination = (count) => (page, total) => {
      const start = max (1, min (page - floor ((count - 3) / 2), total - count + 2))
      const end = min (total, max (page + floor ((count - 2) / 2), count - 1))
      return [
        ... (start > 2 ? [1, '...'] : start > 1 ? [1] : []), 
        ... range (start, end + 1), 
        ... (end < total - 1 ? ['...', total] : end < total ? [total] : [])
      ]
    }
    
    const tests = [
      /* Mobile, 4 pages */   [4, 1, 4], [4, 2, 4], [4, 3, 4], [4, 4, 4],
      /* 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],
      /* Desktop, 7 pages */  [7, 1, 7], [7, 2, 7], [7, 7, 7],
      /* 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],  
    ]
    
    tests .forEach (([c, p, t]) => {
      console .log (`pagination (${c}) (${p}, ${t}) //=> [${pagination (c) (p, t)}]`)
    })
    .as-console-wrapper {max-height: 100% !important; top: 0}

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

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

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

      const end = Math .min (total, Math .max (page + floor ((count - 2) / 2), count - 1))
    

    使用此变体:

      const end = Math .min (total, Math .max (page + floor ((count - 4 + 2 * (count % 2)) / 2), count - 1))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-13
      • 2011-10-31
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 2012-03-26
      • 1970-01-01
      • 2021-02-12
      相关资源
      最近更新 更多