对 Javascript 数组进行分页

问题描述 投票:0回答:15

我正在尝试编写一个 Javascript 函数,它接受

array
page_size
page_number
作为参数,并返回一个模仿分页结果的数组:

paginate: function (array, page_size, page_number) {
  return result;
}

例如当:

array = [1, 2, 3, 4, 5],
page size = 2,
page_number = 2,

该函数应返回:

[3, 4]

任何想法将不胜感激。

javascript arrays pagination
15个回答
342
投票

您可以使用

Array.prototype.slice
并只需提供
(start, end)
的参数。

function paginate(array, page_size, page_number) {
  // human-readable page numbers usually start with 1, so we reduce 1 in the first argument
  return array.slice((page_number - 1) * page_size, page_number * page_size);
}

console.log(paginate([1, 2, 3, 4, 5, 6], 2, 2));
console.log(paginate([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 4, 1));


24
投票

这里有一个解决方案

reduce()

function paginate (arr, size) {
  return arr.reduce((acc, val, i) => {
    let idx = Math.floor(i / size)
    let page = acc[idx] || (acc[idx] = [])
    page.push(val)

    return acc
  }, [])
}

let array = [1, 2, 3, 4, 5]
let page_size = 2
let pages = paginate(array, page_size)

console.log(pages)    // all pages
console.log(pages[1]) // second page

它返回一个页面数组,以便您可以获得特定页面,或循环遍历所有页面。


15
投票

我看到上面的一个例子(某种程度上)正确地做到了这一点,并想对其进行扩展。

这就是例子。

function paginate(array, page_size, page_number) {
  // human-readable page numbers usually start with 1, so we reduce 1 in the first argument
  return array.slice((page_number - 1) * page_size, page_number * page_size);
}

这有一些问题。

1.) 如果

page_number
为 0,那么它将尝试将起始分割设置为
-1 * page_size
,这将返回一个空数组。因此
page_number
属性的最小值应该为 1,绝不能小于 1,除非您在函数中处理这种情况。

2.) 分割的起始索引和结束索引相同。因此,您会得到一个空数组。所以分割应该是:

return array.split(page_number * page_size, page_number * page_size + page_size)

const myArray = [1,2,3,4,5,6,7,8,9,10];

const paginateBad1 = (array, page_size, page_number) => {
  return array.slice((page_number - 1) * page_size, page_number * page_size);
};

const paginateBad2 = (array, page_size, page_number) => {
  return array.slice(page_number * page_size, page_number * page_size);
};

const paginateGood = (array, page_size, page_number) => {
  return array.slice(page_number * page_size, page_number * page_size + page_size);
};

console.log("Bad 1", paginateBad1(myArray, 2, 0));
console.log("Bad 2", paginateBad2(myArray, 2, 1));
console.log("Good", paginateGood(myArray, 2, 1));


4
投票

您可以利用的另一种方法是使用 .filter,看:

const paginate = function (array, index, size) {
        // transform values
        index = Math.abs(parseInt(index));
        index = index > 0 ? index - 1 : index;
        size = parseInt(size);
        size = size < 1 ? 1 : size;

        // filter
        return [...(array.filter((value, n) => {
            return (n >= (index * size)) && (n < ((index+1) * size))
        }))]
    }

var array = [
  {id: "1"}, {id: "2"}, {id: "3"}, {id: "4"}, {id: "5"}, {id: "6"}, {id: "7"}, {id: "8"}, {id: "9"}, {id: "10"}
 ]


var transform = paginate(array, 2, 5);

console.log(transform) // [{"id":"6"},{"id":"7"},{"id":"8"},{"id":"9"},{"id":"10"}] 

4
投票

您可以在第二个参数(数组中正在处理的当前元素的索引)的帮助下使用 Array.filter()

您还需要当前选定的页面以及每页要显示的项目数,以便您可以找到所需元素的最小和最大索引。

const indexMin = selectedPage * elementsPerPage;
const indexMax = indexMin + elementsPerPage;
const paginatedArray = arrayToPaginate.filter(
  (x, index) => index >= indexMin && index < indexMax
);

更新 selectedPage 和/或 elementsPerPage 值将允许返回要显示的正确项目。


3
投票

使用

Array#slice
是预期的答案。

这里我使用 Symbol.iterator 创建一个 iterable

const arr = [1,2,3,4,5,6,7,8,9,10]

function page({arr, pageSize, pageNumber}) {
    const start = pageSize*(pageNumber-1)
    const end = pageSize*pageNumber
    return {
        *[Symbol.iterator]() {
            for(let i = start; i < arr.length && i < end; i++) {
                yield arr[i]
            }
        }
    }
}

console.log([...page({arr, pageSize: 5, pageNumber: 2})])


1
投票

嘿,抱歉,我有点晚了,但我们可以使用

Array.splice(start, end)
方法,只不过这更简单

const page = 2
const step = 2;
const start = page * step - step;
const end = start + step;

const array = [1,2,3,4,5,6]
console.log(array.splice(start, end))

1
投票

下面的示例使用 iter-ops 库(我是作者)。

// our inputs...

const array = [1, 2, 3, 4, 5];

const pageSize = 2;
const pageIndex = 1;

最有效的方法是将数组作为可迭代对象进行处理,因此您只需遍历一次即可。

如果你从来不需要其他页面,那么最快的方法是这样的:

import {pipe, skip, page} from 'iter-ops';

const p = pipe(
      array,
      skip(pageSize * pageIndex), // skip pages we don't want
      page(pageSize) // create the next page
).first;

console.log(p); //=> [3, 4]

如果您确实需要其他页面,那么您可以这样做:

const p = pipe(
      array,
      page(pageSize), // get all pages
      skip(pageIndex) // skip pages we don't want
).first;

console.log(p); //=> [3, 4]

如果您需要进行进一步处理:

const i = pipe(
      array,
      page(pageSize), // get all pages
      skip(pageIndex), // skip pages we don't want
      take(1), // take just one page
      // and so on, you can process it further
);

console.log([...i]); //=> [[3, 4]]

1
投票

这是使用 Array.fromArray.slice

的另一种变体
const paginate = (array, n) => {
  const pageSize = Math.ceil(array.length / n);
 
  return Array.from({ length: pageSize }, (_, index) => {
    const start = index * n;
    return array.slice(start, start + n);
  });
};


1
投票
 for (let pageNum = 1; pageNum <= totalPagesCount; pageNum++){
....
  const chunk = articles.slice(
        (pageNum - 1) * pageSizeNumbered,
        pageNum * pageSizeNumbered,
      );
.....
}

0
投票

function paginate(array, page_size, page_number) {
  // human-readable page numbers usually start with 1, so we reduce 1 in the first argument
  return array.slice((page_number - 1) * page_size, page_number * page_size);
}
var arr = [1, 2, 3, 4, 5, 6]


const options = {
        //page: parseInt(req.query.page) || 1,
        page:1,
        limit:10
        //limit: parseInt(req.query.limit) || 10,
        //customLabels: servCustomLabels,
    };


        let prev_page = 0;
         let next_page = 0;
         let h_p_p = null;
         let h_n_p = null;
         let page_count = Math.ceil((arr.length / options.limit));

        if (options.page >= page_count ){  // 2 3 
            next_page = 0;
        }        
        if(options.page >= 1 && options.page < page_count ){
            next_page = options.page + 1;
            h_n_p = true;
        }else{
            next_page = 0;
            h_n_p = false;
        }

        if(options.page <= 1 ){
            prev_page =0;
            h_p_p = false;
        }else{
            prev_page = options.page -1 ;
            h_p_p = true;
        }
        
        console.log(paginate(arr, 2, 2));
        console.log({paginator: {
                    totalDocs: arr.length,
                    perPage: options.limit,
                    pageCount: page_count,
                    currentPage: options.page,
                    //slNo: 2,
                    hasPrevPage: h_p_p,
                    hasNextPage: h_n_p,
                    prev: prev_page,
                    next: next_page
                }})


0
投票
function paginate(arr, PerPage) {
  let map = {};
  let startPage = 1;
  arr.forEach((current) => {
    if (map[startPage] && map[startPage].length < PerPage) {
      map[startPage].push(current);
    }

    if (!map[startPage]) {
      map[startPage] = [current];
    }

    if (map[startPage] && map[startPage].length >= PerPage) {
      startPage++;
    }
  });

  return map;

}

您将在此链接上找到示例


0
投票

使用

filter
的简单解决方案:

function paginate(array, pageIndex, pageSize) {
  const first = pageIndex * pageSize
  const last = (pageIndex * pageSize) + pageSize
  return array.filter((_, index) => {
    return first <= index && index < last
  })
}

0
投票

我会选择这样的东西;

const paginateArray =  (array, pageNumber, pageSize) => {
    const page = array.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
    return page;
};
    
const array = [1, 2, 3, 4, 5];
const pageSize = 2;
const pageNumber = 2;
    
console.log(paginateArray(array, pageNumber, pageSize));

0
投票

这是一个用例

const data = [...Array(400)].map((_,i) => `${i + 1}`);
const itemsPerPage = 10;
let currentPage = 1;
const nbPages =  Math.ceil(data.length/itemsPerPage) ;
let pagination;

const delay = (ms) => {
  return new Promise ((res, err) => {
    setTimeout(res, ms) 
  })
}

async function fetchData (start, end) {
  await delay(300)
  return await  data.slice(start, end);
}

async function* paginate(data, itemsPerPage) {
    let index = 0;
    while (true) {
        const direction = yield  index;
        if (direction === 'next') {
            index += itemsPerPage;
        } else if (direction === 'prev') {
            index -= itemsPerPage;
        }
        index = Math.max(0, index);
        yield await fetchData(index, index + itemsPerPage);
    }
}

async function nextItems () {
  let res = (await pagination.next("next")).value; 
  pagination.next()
  return res;
}  
 
async function prevtItems () {
  let res =  (await pagination.next("prev")).value;
  pagination.next()
  return res;  
}   

function limitSup () {
  return currentPage == nbPages;
}

function limitInf () {
  return currentPage == 1;
}

function renderView (pageItems) {
  if (typeof(pageItems) != typeof([]))  { 
    alert("too fast")
    return;
  }
  page.innerText = `${currentPage}/${nbPages}`
  results.innerHTML = `
    <table border='0' width="20%">
      <tr><td>Items n°</td><td>value</td></tr>
      ${pageItems.map(it => `
        <tr>
          <td style='padding:1rem'>${it}</td>
          <td>data-${it}</td>
        </tr>`).join('')} 
    </table>
  ` 
}

document.getElementById("next").addEventListener("click", async () => {
  if (limitSup()) return;
  currentPage = Math.min(++currentPage, nbPages)
  renderView (await nextItems())
})

document.getElementById("prev").addEventListener("click", async () => {
  if (limitInf ()) return;
  currentPage = Math.max(--currentPage, 1)
  renderView (await prevtItems())
})


function main () {
  renderView(data.slice(0, itemsPerPage))
  pagination = paginate(data, itemsPerPage);
  pagination.next();
}

main ()

您可以在这里测试它:AsyncPagination

© www.soinside.com 2019 - 2024. All rights reserved.