我正在尝试编写一个 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]
。
任何想法将不胜感激。
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));
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
它返回一个页面数组,以便您可以获得特定页面,或循环遍历所有页面。
我看到上面的一个例子(某种程度上)正确地做到了这一点,并想对其进行扩展。
这就是例子。
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));
您可以利用的另一种方法是使用 .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"}]
您可以在第二个参数(数组中正在处理的当前元素的索引)的帮助下使用 Array.filter()。
您还需要当前选定的页面以及每页要显示的项目数,以便您可以找到所需元素的最小和最大索引。
const indexMin = selectedPage * elementsPerPage;
const indexMax = indexMin + elementsPerPage;
const paginatedArray = arrayToPaginate.filter(
(x, index) => index >= indexMin && index < indexMax
);
更新 selectedPage 和/或 elementsPerPage 值将允许返回要显示的正确项目。
使用
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})])
嘿,抱歉,我有点晚了,但我们可以使用
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))
下面的示例使用 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]]
这是使用 Array.from 和 Array.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);
});
};
for (let pageNum = 1; pageNum <= totalPagesCount; pageNum++){
....
const chunk = articles.slice(
(pageNum - 1) * pageSizeNumbered,
pageNum * pageSizeNumbered,
);
.....
}
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
}})
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;
}
使用
filter
的简单解决方案:
function paginate(array, pageIndex, pageSize) {
const first = pageIndex * pageSize
const last = (pageIndex * pageSize) + pageSize
return array.filter((_, index) => {
return first <= index && index < last
})
}
我会选择这样的东西;
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));
这是一个用例
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