Pagination みたいにリストの中から常に n 件の値を取得する方法を考えてみた。(車輪の再発明)
要件
- リストが
n
件以上ある時は 常にn
件 表示する - current を中心として前後に
n / 2
件づつの範囲を取る - 偶数件の範囲を取る場合は後ろの方を 1 件多くする
- current が前後に
n / 2
件取れない場合は先頭から又は最後からn
件取得する
実装イメージ
Sample
See the Pen Untitled by KIKIKI (@kikiki_kiki) on CodePen.
current の index から開始と終了の index を求める
リストから抽出するので Array.slice()
を使う想定で開始 start
と 終了 end
(範囲の index + 1) を取得できれば良い
type GetSliceRangeProps = { itemLength: number; currentIndex: number; displayNum: number; }; const getSliceRange = ({ itemLength, currentIndex, displayNum }: GetSliceRangeProps): { start: unumber; end?: number; } => { // 表示数がリストより多い場合は全件表示する if (displayNum > itemLength) { return { start: 0, }; } // current の前後に表示する要素数 // 表示数が偶数の場合、前が 1つ少なくなるので Math.floor で少ない数に合わせる const half = Math.floor((displayNum - 1) / 2); // current が前に必要な数に満たない場合は、先頭から表示件数分を表示する if (currentIndex < half) { return { start: 0, end: displayNum, }; } // currentIndex + 後ろに必要な数 がリスト長以上になってしまう場合はリストの後ろから表示件数分を表示する // index は 0 からで、リストの要素数 length は 1 からのカウントなのでリストの最後の要素の index と比較する const lastItemIndex = itemLength - 1; if (currentIndex + half >= lastItemIndex) { return { start: itemLength - displayNum }; } const start = currentIndex - half; const end = start + displayNum; return { start, end, }; }; // 使い方 const {start, end} = getSliceRange({ itemLength: MyArray.length, currentIndex, displayNum }); MyArray.slice(start, end);
index と length 混ざってると混乱しがち。
おわり
[参考]