خوارزمية/رمز زائف لإنشاء روابط الترحيل؟

StackOverflow https://stackoverflow.com/questions/44542

  •  09-06-2019
  •  | 
  •  

سؤال

هل يمكن لشخص ما توفير رمز أو رمز زائف لكيفية إنشاء روابط الترحيل على StackOverflow؟

أستمر في إرهاق ذهني ولكن لا يمكنني التفكير في طريقة مناسبة لبناء الروابط الديناميكية التي تعرض دائمًا الصفحتين حول التيار، بالإضافة إلى الصفحة الأولى والأخيرة.

مثال: 1 ... 5 6 7 ... 593

هل كانت مفيدة؟

المحلول

هناك العديد من الإجابات الأخرى بالفعل، ولكن أود أن أوضح لك النهج الذي اتبعته لحل المشكلة:أولاً، دعونا نتحقق من كيفية تعامل Stack Overflow مع الحالات العادية وحالات الحافة.تعرض كل صفحة من صفحاتي 10 نتائج، لذا لمعرفة ما تفعله في صفحة واحدة، ابحث عن علامة تحتوي على أقل من 11 إدخالاً: سهولة الاستخدام يعمل اليوم.يمكننا أن نرى يتم عرض أي شيء، وهو أمر منطقي.

ماذا عن صفحتين؟ابحث عن علامة تحتوي على ما بين 11 و20 إدخالاً (ايماكس يعمل اليوم).نحن نرى:"1 2 التالي" أو "السابق 1 2"، اعتمادًا على الصفحة التي نتواجد فيها.

3 صفحات؟"1 2 3 ...3 التالي"، "السابق 1 2 3 التالي"، و"السابق 1...2 3".ومن المثير للاهتمام أننا يمكننا أن نرى أن Stack Overflow نفسه لا يتعامل مع حالة الحافة هذه بشكل جيد:يجب أن يعرض "1 2 ...3 التالي"

4 صفحات؟"1 2 3 ...4 التالي"، "السابق 1 2 3 ...4 التالي"، "السابق 1 ...2 3 4 التالي" و"السابق 1...3 4"

أخيرًا، دعونا نلقي نظرة على الحالة العامة، الصفحات N:"1 2 3 ...N التالي"، "السابق 1 2 3 ...N التالي"، "السابق 1 ...2 3 4 ...N التالي"، "السابق 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

تعمل هذه الوظيفة بشكل جيد، ولكنها لا تأخذ في الاعتبار ما إذا كنا بالقرب من الصفحة الأولى أو الأخيرة.بالنظر إلى الأمثلة المذكورة أعلاه، نريد فقط عرض ...إذا كانت الصفحة الحالية بعيدة عن موقعين أو أكثر.

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

لم يتبق سوى مشكلتين.أولاً، نحن لا نطبع بشكل صحيح لصفحة واحدة، وثانيًا، سنقوم بطباعة "1" مرتين إذا كنا في الصفحة الأولى أو الأخيرة.دعونا ننظفهما دفعة واحدة:

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

في الحقيقة لقد كذبت:لدينا قضية واحدة متبقية.عندما يكون لديك 4 صفحات على الأقل وتكون في الصفحة الأولى أو الأخيرة، تحصل على صفحة إضافية في شاشتك.بدلاً من "1 2 ...10 التالي "تحصل على"1 2 3 ...10 التالي".لمطابقة ما يحدث في 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 أو Pc > (Pn-3)}

  • الخطوة الأولى هي تحديد عدد الصفحات بشكل واضح:

numPages = ceiling(totalRecords / numPerPage)

  • إذا كان لديك 4 أو أقل، فسيتم التسرب في هذه المرحلة، لأنه وفقًا للقواعد المذكورة أعلاه، سيكون الترحيل دائمًا ثابتًا (P1، P2، Pn-1، Pn)، حيث سيكون أحدهما Pc تمامًا

  • وإلا، لديك ثلاث "دول"

أ.(Pc < P3) - لذا قم بإظهار P1، P2، P3، Pn، Next إذا كان Pc > 1، قم بإظهار الرابط "السابق" قبل P1.

ب.(Pc > Pn - 2)، لذا قم بإظهار Prev، P1، Pn - 2، Pn -1، Pn، قم بإظهار الرابط التالي إذا كان Pc < Pn

ج.إظهار السابق، P1، Pc -1، Pc، Pc +1، Pn، التالي

سهل مثل الفطيرة في الكود الزائف.يمكن أن تصبح الحلقات سيئة بعض الشيء عند تنفيذها حيث يتعين عليك القيام ببعض التكرار لإنشاء الروابط.

يحرر:بالطبع 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).

أمم.في الواقع ، في حالة أن page current هو 3 ، فإنه لا يزال يظهر [1] ... [2] [3] [4] ... [xxx] أعتقد أن القطع غير ضرورية في هذه الحالة.ولكن هذه هي الطريقة التي تعمل بها.

يحرر:تقوم المعاينة بتنسيق مجموعة التعليمات البرمجية بشكل صحيح، فلماذا تتشوه؟أكيد هو مجرد كود وهمي....لكن مازال....

هذا هو أسلوبي لإنشاء رابط الترحيل.الأتى كود جافا هو مجرد زائفة.

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

}

هذه هي الخوارزمية الخاصة بي وهي تعمل بشكل رائع حقًا:

    // 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

لذلك يمكنك عمل بيجر مثل هذا:

    if prevPage
    [1] [prevPage] 
    endif

    [startPage] ... [endPage] 

    if nextPage
    [nextPage] [lastPage] 
    endif

أو تخصيص ما تريد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top