Algorithmus/Pseudocode zum Erstellen von Paging-Links?
Frage
Kann jemand Code oder Pseudocode dafür bereitstellen, wie die Paging-Links auf StackOverflow generiert werden?
Ich zerbreche mir ständig den Kopf, kann mir aber keine vernünftige Möglichkeit vorstellen, die dynamischen Links zu erstellen, die immer die beiden Seiten rund um die aktuelle sowie die erste und die letzte anzeigen.
Beispiel: 1 ... 5 6 7 ... 593
Lösung
Es gibt bereits mehrere andere Antworten, aber ich möchte Ihnen den Ansatz zeigen, den ich zur Lösung des Problems gewählt habe:Schauen wir uns zunächst an, wie Stack Overflow mit Normalfällen und Randfällen umgeht.Auf jeder meiner Seiten werden 10 Ergebnisse angezeigt. Um also herauszufinden, was sie für eine Seite bewirkt, suchen Sie nach einem Tag mit weniger als 11 Einträgen: Benutzerfreundlichkeit funktioniert heute.Wir können sehen, dass nichts angezeigt wird, was Sinn macht.
Wie wäre es mit 2 Seiten?Suchen Sie ein Tag mit zwischen 11 und 20 Einträgen (Emacs funktioniert heute).Wir sehen:"1 2 Weiter“ oder „Zurück 1“. 2", je nachdem, auf welcher Seite wir uns befinden.
3 Seiten?"1 2 3 ...3 Weiter“, „Vorherige 1 2 3 Weiter“ und „Vorherige 1 ...“2 3".Interessanterweise können wir sehen, dass Stack Overflow selbst diesen Randfall nicht sehr gut bewältigt:es sollte „anzeigen“1 2 ...3 Weiter"
4 Seiten?"1 2 3 ...4 Weiter“, „Vorherige 1 2 3 ...4 Weiter“, „Vorherige 1 ...2 3 4 Weiter“ und „Vorherige 1 ...“3 4"
Schauen wir uns zum Schluss den allgemeinen Fall an, N Seiten:"1 2 3 ...N Nächster“, „Vorheriger 1 2 3 ...N Weiter“, „Vorherige 1 ...“2 3 4 ...N Weiter“, „Vorherige 1 ...“3 4 5 ...„N Weiter“ usw.
Lassen Sie uns basierend auf dem, was wir gesehen haben, verallgemeinern:Der Algorithmus scheint diese gemeinsamen Merkmale zu haben:
- Wenn wir uns nicht auf der ersten Seite befinden, zeigen Sie den Link zur vorherigen Seite an
- Zeigen Sie immer die erste Seitenzahl an
- Zeigt immer die aktuelle Seitenzahl an
- Zeigen Sie immer die Seite vor dieser Seite und die Seite nach dieser Seite an.
- Zeigt immer die letzte Seitenzahl an
- Wenn wir uns nicht auf der letzten Seite befinden, zeigen Sie den Link „Weiter“ an
Lassen Sie uns den Randfall einer einzelnen Seite ignorieren und einen guten ersten Versuch mit dem Algorithmus unternehmen:(Wie bereits erwähnt, wäre der Code zum tatsächlichen Ausdrucken der Links komplizierter.Stellen Sie sich jede Stelle vor, an der wir eine Seitennummer (Vorherige oder Nächste) platzieren, als einen Funktionsaufruf, der die richtige URL zurückgibt.)
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
Diese Funktion funktioniert einwandfrei, berücksichtigt jedoch nicht, ob wir uns in der Nähe der ersten oder letzten Seite befinden.Wenn wir uns die obigen Beispiele ansehen, möchten wir nur die ... anzeigen.wenn die aktuelle Seite zwei oder mehr entfernt ist.
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
Wie Sie sehen, gibt es hier einige Duplikate.Wir können das zur besseren Lesbarkeit bereinigen:
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
Es bleiben nur noch zwei Probleme.Erstens drucken wir eine Seite nicht korrekt aus und zweitens drucken wir „1“ zweimal aus, wenn wir uns auf der ersten oder letzten Seite befinden.Lassen Sie uns beides auf einmal bereinigen:
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
Eigentlich habe ich gelogen:Wir haben noch ein Problem.Wenn Sie mindestens 4 Seiten haben und sich auf der ersten oder letzten Seite befinden, erhalten Sie eine zusätzliche Seite in Ihrer Anzeige.Anstatt "1 2 ...10 Als nächstes erhalten Sie1 2 3 ...10 Weiter".Um genau zu ermitteln, was bei Stack Overflow vor sich geht, müssen Sie die folgende Situation prüfen:
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
Ich hoffe das hilft!
Andere Tipps
Die Steuerelemente zeigen im Allgemeinen Steuerelemente für:P1, Pn, Pc (aktuelle Seite), Pc+1, Pc-1.Dies ändert sich nur an beiden Enden des Paging-Bereichs {Pc < P3 oder Pc > (Pn-3)}
- Der erste Schritt besteht natürlich darin, die Anzahl der Seiten zu ermitteln:
numPages = ceiling(totalRecords / numPerPage)
Wenn Sie 4 oder weniger haben, brechen Sie an dieser Stelle ab, da nach den oben genannten Regeln das Paging immer festgelegt ist (P1, P2, Pn-1, Pn), wobei man tatsächlich Pc sein wird
Ansonsten haben Sie drei „Zustände“
A.(Pc < P3) – also P1, P2, P3, Pn, Next anzeigen. Wenn Pc >1, wird vor P1 ein „Prev“-Link angezeigt.
B.(Pc > Pn - 2), also zeige Prev, P1, Pn - 2, Pn -1, Pn, zeige einen Next-Link, wenn Pc < Pn
C.Show Prev, P1, Pc -1, Pc, Pc +1, Pn, Next
Kinderleicht im Pseudocode.Die Schleifen können bei der Implementierung etwas unangenehm werden, da Sie einige Iterationen durchführen müssen, um die Links zu generieren.
Bearbeiten:Natürlich sind Prev und Next identisch mit Pc +/- 1
Nun, wenn Sie die aktuelle Seite kennen, ist es ziemlich trivial, einfach die Zahl um 1 zu subtrahieren und um 1 zu addieren, diese Zahlen dann mit den Grenzen zu vergleichen und immer die erste und letzte Seite anzuzeigen, auch wenn sie nicht in der richtigen Reihenfolge sind , füge die Ellipsen hinzu.
Oder möchten Sie die Gesamtzahl der Seiten ermitteln und die aktuelle Seitenzahl ermitteln ...?
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 wird als Math.Ceiling(totalRecords/RecordsPerPage) berechnet.
Hmmm.In dem Fall, dass CurrentPage 3 ist, zeigt es immer noch [1] ... [2] [3] [4] ... [xxx] Ich denke, die Ellipsen sind in diesem Fall überflüssig.Aber so funktioniert es.
Bearbeiten:Die Vorschau formatiert den Codeblock korrekt. Warum wird er verstümmelt?Klar, es ist nur Pseudocode ...aber dennoch....
Dies ist mein Ansatz, um einen Paging-Link zu erstellen.Die folgende Java-Code ist nur ein Pseudo.
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);
}
}
}
Hier ist mein Algorithmus, der wirklich gut funktioniert:
// Input
total_items // Number of rows, records etc. from db, file or whatever
per_page // num items per page
page // current page
visible_pages // number of visible pages
// Calculations
lastPage = ceil(total_items / per_page);
prevPage = page - 1 < 1 ? 0 : page - 1;
nextPage = page + 1 > lastPage ? 0 : page + 1;
halfpages = ceil(visible_pages / 2);
startPage = page - halfpages < 1 ? 1 : page - halfpages;
endPage = startPage + visible_pages - 1;
if(endPage > lastPage) {
startPage -= endPage - lastPage;
startPage = startPage < 1 ? 1 : startPage;
endPage = startPage + visible_pages > lastPage ? lastPage : startPage + visible_pages - 1;
}
// Output
lastPage // Total number of pages
prevPage // Previous page number (if 0 there is no prev page)
nextPage // Next page number (if 0 there is no next page)
startPage // First visible page
endPage // Last visible page
So können Sie einen Pager wie diesen erstellen:
if prevPage
[1] [prevPage]
endif
[startPage] ... [endPage]
if nextPage
[nextPage] [lastPage]
endif
oder passen Sie alles an, was Ihnen gefällt.