StackOverflowのページングリンクを生成する方法のコードまたは擬似コードを提供できる人はいますか?
私は頭を悩ませ続けていますが、常に現在の2ページに加えて、最初と最後のページを表示する動的リンクを構築するための適切な方法を考えることはできません。
例:1 ... 5 6 7 ... 593
すでに他にもいくつかの回答がありますが、それを解決するために私が取ったアプローチをお見せしたいと思います。まず、スタック オーバーフローが通常のケースとエッジ ケースをどのように処理するかを確認しましょう。私のページにはそれぞれ 10 件の結果が表示されるので、1 ページでの結果を調べるには、エントリが 11 未満のタグを見つけます。何も表示されていないことがわかります。これは理にかなっています。
2ページでどうですか?11 から 20 のエントリを持つタグを見つけます ( emacsは現在動作しています)。現在のページに応じて、" 1 2 Next" または "Prev 1 2 " が表示されます。
3ページ?「1 2 3 ... 3 次へ」、「前へ 1 2 3 次へ」、「前へ 1 ... 2 3」。興味深いことに、スタック オーバーフロー自体がこのエッジ ケースをうまく処理していないことがわかります。「1 2 ... 3 次へ」と表示されるはずです。
4ページ?" 1 2 3 ... 4 次へ"、"前へ 1 2 3 ... 4 次へ"、"前へ 1 ... 2 3 4 次へ"、"前へ 1 ... 3 4 "
最後に、N ページの一般的なケースを見てみましょう: " 1 2 3 ... N Next"、"Prev 1 2 3 ... N Next"、"Prev 1 ... 2 3 4 ... N Next"、 「前へ 1 ... 3 4 5 ... N 次へ」など
これまで見てきたことに基づいて一般化しましょう: アルゴリズムには、次の共通の特徴があるようです。
単一のページのエッジ ケースを無視して、アルゴリズムで最初の適切な試行を行いましょう: (前述のように、リンクを実際に出力するコードはより複雑になります。ページ番号、前または次を配置する各場所を想像してください。正しい URL を返す関数呼び出しとして。)
function printPageLinksFirstTry(num totalPages, num currentPage)
if ( currentPage > 1 )
print "Prev"
print "1"
print "..."
print currentPage - 1
print currentPage
print currentPage + 1
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
この関数は問題なく動作しますが、最初のページに近づいているか最後のページに近づいているかは考慮されていません。上記の例を見ると、現在のページが 2 つ以上離れている場合にのみ ... を表示したいと考えています。
function printPageLinksHandleCloseToEnds(num totalPages, num currentPage)
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
if ( currentPage > 2 )
print currentPage - 1
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
if ( currentPage < totalPages - 1 )
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
ご覧のとおり、ここにはいくつかの重複があります。先に進み、読みやすくするためにクリーンアップできます。
function printPageLinksCleanedUp(num totalPages, num currentPage)
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
print currentPage - 1
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
残っている問題は 2 つだけです。まず、1 ページを正しく印刷しません。次に、最初または最後のページにいる場合、「1」を 2 回印刷します。これらの両方を一度にクリーンアップしましょう。
function printPageLinksFinal(num totalPages, num currentPage)
if ( totalPages == 1 )
return
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
print currentPage - 1
if ( currentPage != 1 and currentPage != totalPages )
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
実は、私は嘘をつきました: 残りの問題が 1 つあります。少なくとも 4 ページあり、最初または最後のページにいる場合、ディスプレイに余分なページが表示されます。" 1 2 ... 10 Next" の代わりに " 1 2 3 ... 10 Next" になります。Stack Overflow で起こっていることと正確に一致させるには、次の状況を確認する必要があります。
function printPageLinksFinalReally(num totalPages, num currentPage)
if ( totalPages == 1 )
return
if ( currentPage > 1 )
print "Prev"
print "1"
if ( currentPage > 2 )
print "..."
if ( currentPage == totalPages and totalPages > 3 )
print currentPage - 2
print currentPage - 1
if ( currentPage != 1 and currentPage != totalPages )
print currentPage
if ( currentPage < totalPages - 1 )
print currentPage + 1
if ( currentPage == 1 and totalPages > 3 )
print currentPage + 2
print "..."
print totalPages
if ( currentPage < totalPages )
print "Next"
endFunction
これが役立つことを願っています!
コントロールは通常、P1、Pn、Pc (現在のページ)、Pc+1、Pc-1 のコントロールを表示します。これが変化するのは、ページング範囲 {Pc < P3 or Pc > (Pn-3)} の両端だけです。
numPages = ceiling(totalRecords / numPerPage)
4 つ以下の場合は、この時点で脱落します。これは、上記のルールにより、ページングが常に固定されるため (P1、P2、Pn-1、Pn)、1 つが実際には Pc になるためです。
それ以外の場合は、3 つの「状態」があります
を。(Pc < P3) - P1、P2、P3、Pn、Next を表示 Pc >1 の場合、P1 の前に「前」リンクを表示します。
b. (Pc > Pn - 2)、したがって Prev、P1、Pn - 2、Pn -1、Pn を表示し、Pc < Pn の場合は次のリンクを表示
c. Prev、P1、Pc -1、Pc、Pc +1、Pn、Next を表示
疑似コードの Pie のように簡単です。リンクを生成するためにいくつかの反復を行う必要があるため、ループを実装すると少し厄介になる可能性があります。
編集: もちろん Prev と Next は Pc +/- 1 と同じです
現在のページがわかっている場合は、数値を 1 減算して 1 を加算し、それらの数値を境界に対してチェックし、最初と最後のページを常に表示するのは非常に簡単です。 、楕円を追加します。
それとも、総ページ数を取得して現在のページ番号を決定することについて質問していますか?
public void PageLinks(int currentPage, int lastPage) {
if (currentPage > 2)
Add('[1]', '...');
for(int i=Math.Max(1, currentPage-1); i< Math.Min(currentPage+1, lastPage); i++)
Add('[i]');
if (currentPage < lastPage-1)
Add('...', '[lastpage]');
}
lastPage は、Math.Ceiling(totalRecords/RecordsPerPage) として計算されます。
うーん。実際には、currentpage が 3 の場合でも、[1]...[2][3][4]...[xxx] と表示されます。その場合、省略記号は不要だと思います。しかし、それはそれがどのように機能するかです。
編集: プレビューはコードブロックを正しくフォーマットしますが、なぜ壊れてしまうのでしょうか? 確かに、それは単なる疑似コードです....しかし、それでも....
これは、ページング リンクを作成するための私のアプローチです。次のJava コードは単なる疑似コードです。
package com.edde;
/**
* @author Yang Shuai
*/
public class Pager {
/**
* This is a method used to display the paging links(pagination or sometimes called pager).
* The totalPages are the total page you need to display. You can get this value using the
* formula:
*
* total_pages = total_records / items_per_page
*
* This methods is just a pseudo-code.
*
*
* @param totalPages how many pages you need to display
* @param currentPage you are in which page now
*/
public static void printPageLinks(int totalPages, int currentPage) {
// how many pages to display before and after the current page
int x = 2;
// if we just have one page, show nothing
if (totalPages == 1) {
return;
}
// if we are not at the first page, show the "Prev" button
if (currentPage > 1) {
System.out.print("Prev");
}
// always display the first page
if (currentPage == 1) {
System.out.print(" [1]");
} else {
System.out.print(" 1");
}
// besides the first and last page, how many pages do we need to display?
int how_many_times = 2 * x + 1;
// we use the left and right to restrict the range that we need to display
int left = Math.max(2, currentPage - 2 * x - 1);
int right = Math.min(totalPages - 1, currentPage + 2 * x + 1);
// the upper range restricted by left and right are more loosely than we need,
// so we further restrict this range we need to display
while (right - left > 2 * x) {
if (currentPage - left < right - currentPage) {
right--;
right = right < currentPage ? currentPage : right;
} else {
left++;
left = left > currentPage ? currentPage : left;
}
}
// do we need display the left "..."
if (left >= 3) {
System.out.print(" ...");
}
// now display the middle pages, we display how_many_times pages from page left
for (int i = 1, out = left; i <= how_many_times; i++, out++) {
// there are some pages we need not to display
if (out > right) {
continue;
}
// display the actual page
if (out == currentPage) {
System.out.print(" [" + out + "]");
} else {
System.out.print(" " + out);
}
}
// do we need the right "..."
if (totalPages - right >= 2) {
System.out.print(" ...");
}
// always display the last page
if (currentPage == totalPages) {
System.out.print(" [" + totalPages + "]");
} else {
System.out.print(" " + totalPages);
}
// if we are not at the last page, then display the "Next" button
if (currentPage < totalPages) {
System.out.print(" Next");
}
System.out.println();
}
public static void main(String[] args) {
// printPageLinks(50, 3);
help(500);
}
public static void test(int n) {
for (int i = 1; i <= n; i++) {
printPageLinks(n, i);
}
System.out.println("------------------------------");
}
public static void help(int n) {
for (int i = 1; i <= n; i++) {
test(i);
}
}
public static void help(int from, int to) {
for (int i = from; i <= to; i++) {
test(i);
}
}
}