admin管理员组文章数量:1129458
I am trying to write a Javascript function that takes an array
, page_size
and page_number
as parameters and returns an array that mimics paginated results:
paginate: function (array, page_size, page_number) {
return result;
}
so for example when:
array = [1, 2, 3, 4, 5],
page size = 2,
page_number = 2,
the function should return: [3, 4]
.
Any ideas would be appreciated.
I am trying to write a Javascript function that takes an array
, page_size
and page_number
as parameters and returns an array that mimics paginated results:
paginate: function (array, page_size, page_number) {
return result;
}
so for example when:
array = [1, 2, 3, 4, 5],
page size = 2,
page_number = 2,
the function should return: [3, 4]
.
Any ideas would be appreciated.
Share Improve this question asked Mar 13, 2017 at 10:12 SalmaFGSalmaFG 2,1925 gold badges25 silver badges37 bronze badges 4 |16 Answers
Reset to default 358You can use Array.prototype.slice
and just supply the params for (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));
Here's a solution with 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
It returns an array of pages so you can get a certain page, or loop through all of them.
I saw an example above that did this correctly (kind of) and wanted to expand on it.
This was the example.
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);
}
There are a few things wrong with this.
1.) If the page_number
is 0 then it will try and set the starting split at -1 * page_size
which returns an empty array. So the minimum value of the page_number
attr should be 1, never anything less unless you handle that case in the function.
2.) The starting and ending index of the split are the same. Because of this, you get back an empty array. So the split should be:
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));
Another aproach that you can utilize, is using .filter, look:
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"}]
You can use Array.filter() with the help of its second parameter (the index of the current element being processed in the array).
You'll also need the currently selected page and the number of items per page to display, so you can find the minimum and maximum index of the elements needed.
const indexMin = selectedPage * elementsPerPage;
const indexMax = indexMin + elementsPerPage;
const paginatedArray = arrayToPaginate.filter(
(x, index) => index >= indexMin && index < indexMax
);
Updating the selectedPage and/or the elementsPerPage value will allow to return the correct items to display.
The use of Array#slice
is the expected answer.
Here I use Symbol.iterator to create an 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})])
The example below is using iter-ops library (I'm the author).
// our inputs...
const array = [1, 2, 3, 4, 5];
const pageSize = 2;
const pageIndex = 1;
The most efficient way is to process an array as an iterable, so you go through it once.
If you never need other pages, then the fastest way is like this:
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]
And if you do need other pages, then you can do:
const p = pipe(
array,
page(pageSize), // get all pages
skip(pageIndex) // skip pages we don't want
).first;
console.log(p); //=> [3, 4]
And in case you need to do further processing:
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]]
Here is another variation using Array.from with 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);
});
};
Hey I'm sorry I'm a bit late but we can use the Array.splice(start, end)
method except this is much simpler
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))
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;
}
you will find an example on this link
A simple solution using filter
:
function paginate(array, pageIndex, pageSize) {
const first = pageIndex * pageSize
const last = (pageIndex * pageSize) + pageSize
return array.filter((_, index) => {
return first <= index && index < last
})
}
I'd go with something like this;
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));
Here is a use case
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 ()
You can test it here : AsyncPagination
const data = []
for (const index of Array.from({ length: 43}, (v, i) => i)) {
data.push(index)
}
const page = 1
const perPage = 5
const registers = data.length
const totalPages = Math.ceil(registers / perPage)
const start = (page - 1) * perPage
const end = page * perPage
const result = data.slice(start, end)
if (page > totalPages) throw new Error(`invalid page: last page: ${totalPages}`)
console.log({ page, perPage, registers, totalPages, data: result })
// { page: 1, perPage: 5, registers: 43, totalPages: 9, data: [ 0, 1, 2, 3, 4 ] }
本文标签: Paginate Javascript arrayStack Overflow
版权声明:本文标题:Paginate Javascript array - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736740329a1950475.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
[3, 4]
represent in relation to all the other variables? It's kind of key that you explain that explicitly – StudioTime Commented Mar 13, 2017 at 10:14Array.slice
->array.slice((page_number - 1) * page_size, page_size)
(something like that should work) – casraf Commented Mar 13, 2017 at 10:15[1, 2]
,[3, 4]
and[5]
. Page number 2 in this scenario will be[3, 4]
. – SalmaFG Commented Mar 13, 2017 at 10:18