如何解决获取数组的每个第 n 个元素 游乐场
我正在编写一个辅助函数来获取数组中的每个 nth
元素,以便根据列的索引获取特定列的所有表格单元格。
我是根据 this thread 的回答得出的。
我担心的是,每当我传递列索引 0 时,它都不起作用。 我也不太确定应该将增量更改为什么,因为它不会产生正确的结果。
给定以下数组
const cells = [
'text','text','button',];
并通过 getColumnCells(cells,6)
调用该函数,我应该会收到一组“按钮”。
const getColumnCells = (cells,columnIndex) => {
const columnCells = [];
const delta = Math.floor(cells.length / columnIndex);
for (let i = columnIndex; i < cells.length; i = i + delta) {
columnCells.push(cells[i]);
}
return columnCells;
};
getColumnCells(cells,0)
应该返回 ['text','text]
以获取每行的索引 0。
解决方法
您可以使用简单的 filter 和 %
(模)运算来实现这一点。但是您需要知道 row
的长度,因为看起来您想将一维数组视为二维数组。
解决方案:
const cells = [
'texta1','texta2','texta3','texta4','texta5','texta6','buttona','textb1','textb2','textb3','textb4','textb5','textb6','buttonb','textc1','textc2','textc3','textc4','textc5','textc6','buttonc',];
const getEveryNth = (arr,rowLength,colIdx) => arr.filter(
(_,i) => i % rowLength === colIdx
)
console.log(getEveryNth(cells,7,6))
console.log(getEveryNth(cells,0))
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore this */
我建议在函数中再传递一个变量 cols
。
您可以在未来一天再添加一列。
然后,您可以将 cols
的不同参数传递给函数以获取输出。
const cells = [
'text','text','button',];
function getColumnCells(arr,cols,index) {
const output = [];
if (cols > index) {
for (let i = 0; i < arr.length; i += cols) {
const row = arr.slice(i,i + cols);
index > row.length ? output.push(null) : output.push(row[index]);
}
}
return output;
}
console.log(getColumnCells(cells,6));
解决方案 1:您可以假设您有 7 列,并将其用作偏移量/增量。
const cells = [
'text','texts',];
const getColumnCells = (cells,columnIndex) => {
const columnCells = [];
const numberOfColumns = 7
const delta = numberOfColumns // or equals to number of columns
for (let i = columnIndex; i < cells.length; i = i + delta) {
columnCells.push(cells[i]);
}
return columnCells;
};
console.log(getColumnCells(cells,3)) // ['texts','texts']
console.log(getColumnCells(cells,6)) // ['button','button']
解决方案 2:简单的一个 一个 3 行 7 列的数组。所以,重塑你的数据
const newCells = [
['text0','text1','text2','text3','text4','button'],['text0',];
const getColumnCellsTwo = (cells,columnIndex) => {
const columnCells = [];
for (let k = 0; k < cells.length; k++) {
columnCells.push(cells[k][columnIndex]);
}
return columnCells;
};
console.log(getColumnCellsTwo(newCells,0)) // ['text0','text0','text0']
console.log(getColumnCellsTwo(newCells,'button']
//最后一条评论是:在您的代码中,当 columnIndex = 0 时,delta = Math.floor(cells.length / columnIndex) 为无穷大。只是为了澄清。
,const cells = ['text1','text5','text6','button7'];
function breakInN(arr,chunk) {
chunk--;
return arr.filter((x,i) => i % chunk == 0 && (i+chunk != 0) || chunk == 0);
}
const output = breakInN(cells,1);
console.log({
output
})
const cells = [
'text',columnIndex) => {
const columnCells = [];
const delta = columnIndex + 1;
// Starting at -1 (ignoring -1) so we always move by 7 and push the 7th element `button`
for (let i = -1; i < cells.length; i = i + delta) {
if (i != -1) {
columnCells.push(cells[i]);
}
}
return columnCells;
};
console.log(getColumnCells(cells,6));
,
我想您的目标是能够将 cells
视为矩阵/表状结构(基本上是 2d array)。在进行任何过滤或选择之前,您可以通过转换您的一维数组为实际矩阵来模拟该行为。以后的工作都会轻松很多。
如果您想按照您在问题中描述的方式处理一维数组,恐怕除了传递某种列数量和列索引之外别无他法。
const cells = [
'text0',];
const arrayToMatrix = (array,cols) =>
Array(Math.floor(array.length / cols))
.fill()
.reduce((acc,_,i) => [...acc,[...array].splice(i * cols,cols)],[]);
const getColumnCells = (cells,colIndex) =>
arrayToMatrix(cells,cols).map((e) => e[colIndex]);
console.log(getColumnCells(cells,6));
console.log(getColumnCells(cells,0));
我的方法的缺点是你需要非常小心你传递给 getColumCell()
的参数,因为 arrayToMatrix()
可能返回一个不完整矩阵,因此你会结束列值为 undefined
。
如果给自己足够的时间来获得更通用的解决方案,则可以实现一个 prototypal Array.nthItem
方法,该方法通过 is inspired :nth-child()
CSS pseudo-class 但基于零/0
索引而不是 1
...
const cells = [
'texta1',];
function processItem(nthItem,nthIndex,array) {
console.log({ nthItem,nthIndex });
// - any passed argument can be processed.
// - this callback is aware of it's `this` context.
// - the callback's return value will be mapped to the
// `nthItem`'s internal array of to be processed indices
// which also,entirely mapped,is the `nthItem`'s return value.
return nthItem;
}
console.log(
"cells.nthItem('7n-1',processItem) ...",cells.nthItem('7n-1',processItem)
);
console.log(
"cells.nthItem('7n-5',cells.nthItem('7n-5',processItem)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<!--
https://gist.github.com/petsel/86d7ce468512fffdb051bf9e650d1e4f
//-->
<script>
const
arrPrototype = Object.getPrototypeOf([]);
const {
from: arrayFrom,isArray,} = Array;
function isFunction(type) {
return (
(typeof type === 'function')
&& (typeof type.call === 'function')
&& (typeof type.apply === 'function')
);
}
function getSanitizedTarget(type) {
return (type ?? null);
}
function getNotationGroup(notation) {
// - inspired by `:nth-child()` CSS pseudo-class ... [https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child]
//
// - an array's `nth-item` notation ... [https://regex101.com/r/tZmeZS/1/]
//
const regXNthItemNotation = (/^(?<nthBase>[+-]?\d+)(?:\*?(?<series>n)(?<crementer>[+-]\d+)?)?$/);
const regXSanitizeNotation = (/\s+/g);
return String(notation)
.replace(regXSanitizeNotation,'')
.match(regXNthItemNotation)
?.groups;
}
function getNthIndexSeriesDescending(getNthIndex,maximumIndex) {
const nthIndexList = [];
let nthIndex;
let n = -1;
while ((nthIndex = getNthIndex(++n)) >= 0) {
if (nthIndex <= maximumIndex) {
nthIndexList.push(nthIndex);
}
}
return nthIndexList;
}
function getNthIndexSeriesAscending(getNthIndex,maximumIndex) {
const nthIndexList = [];
let nthIndex;
let n = -1;
while ((nthIndex = getNthIndex(++n)) <= maximumIndex) {
if (nthIndex >= 0) {
nthIndexList.push(nthIndex);
}
}
return nthIndexList;
}
function getNthIndexSeriesList(notationGroup,maximumIndex) {
const nthIndexList = [];
let { series,nthBase,crementer } = notationGroup;
nthBase = Number(nthBase);
crementer = Number(crementer ?? 0);
const getNthIndex = n => ((nthBase * n) + crementer);
if (!!series) {
if (nthBase !== 0) {
const isDescending = (getNthIndex(0) > getNthIndex(1));
nthIndexList.push(
...isDescending
? getNthIndexSeriesDescending(getNthIndex,maximumIndex)
: getNthIndexSeriesAscending(getNthIndex,maximumIndex)
);
} else if (crementer >= 0) {
// `crementer` in this case equals the result of the first nth-index computation.
nthIndexList.push(crementer);
}
} else if ((nthBase >= 0) && (nthBase <= maximumIndex)) {
// just the `nthBase` as the sole nth-index item.
nthIndexList.push(nthBase);
}
return nthIndexList;
}
function nthItem(notation,callback,target) {
let result = [];
const notationGroup = getNotationGroup(notation);
const arr = notationGroup && ((isArray(this) && this) || arrayFrom(this ?? []));
// fail silently.
const nthIndexList = arr && isFunction(callback) && getNthIndexSeriesList(notationGroup,(arr.length - 1));
if (nthIndexList && nthIndexList.length) {
target = getSanitizedTarget(target);
result = nthIndexList.map(nthIndex =>
callback.call(target,arr[nthIndex],arr)
);
}
return result;
}
Object.defineProperty(arrPrototype,'nthItem',{
configurable: true,writable: true,value: nthItem
});
Object.defineProperty(arrPrototype.nthItem,'toString',{
value: () => 'function nthItem() { [custom code] }'
});
// export default Array;
</script>
游乐场
九之七方法
... nth(7).of(9)
... 基于索引 1
...
const cells = [
'a1','a2','a3','a4','a5','a6','a7','a8','a9','b1','b2','b3','b4','b5','b6','b7','b8','b9','c1','c2','c3','c4','c5','c6','c7','c8','c9',];
console.log(
"cells.nth(7).of(9).map(({ item }) => item) ...",cells.nth(7).of(9).map(({ item }) => item)
);
console.log(
"cells.nth(7).of(9) ...",cells.nth(7).of(9)
);
console.log(
"cells.nth(3).of(6) ...",cells.nth(3).of(6)
);
console.log(
"cells.nth(2).of(3) ...",cells.nth(2).of(3)
);
console.log(
"cells.nth ...",cells.nth
);
console.log(
"cells.nth(2) ...",cells.nth(2)
);
console.log(
"cells.nth(2).of ...",cells.nth(2).of
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<!--
https://gist.github.com/petsel/42d89ad83cc5e90dc0f61a4d030fc17d
//-->
<script>
const
arrPrototype = Object.getPrototypeOf([]);
const {
from: arrayFrom,} = Array;
function createListOfChunkLists(arr,chunkCount) {
return arr.reduce((list,item,idx) => {
if (idx % chunkCount === 0) {
list.push([ item ]);
} else {
// list.at(-1).push(item);
list[list.length - 1].push(item);
}
return list;
},[]);
}
function getNthItemOfChunkCount(arr,chunkCount) {
if (!isArray(arr)) {
throw (new TypeError(
'The "nth().of()" chain needs to operate a list like structure.'
));
}
if (Number.isNaN(chunkCount)) {
throw (new TypeError(
'The chunk count needs to be an integer value.'
));
}
if (chunkCount > arr.length) {
throw (new RangeError(
"The chunk count value has to be lower than or equal to the operated list structure's length."
));
}
if (
Number.isNaN(nthIndex)
|| (nthIndex < 0)
//|| ((nthIndex < 0) && ((nthIndex + chunkCount) <= 0))
|| ((nthIndex >= 0) && ((nthIndex + 1) >= chunkCount))
) {
throw (new RangeError(
"The nth index needs to be an integer value which has to be reasonable within the chunk count's context."
));
}
return createListOfChunkLists(arr,chunkCount)
.map((chunkList,idx) => ({
item: chunkList[nthIndex],idx: ((idx * chunkCount) + nthIndex),}));
}
class NthItemOfChunkCount {
#arr;
#idx;
constructor(arr,idx) {
this.#arr = arr;
this.#idx = idx;
}
of(int) {
return getNthItemOfChunkCount(this.#arr,this.#idx,parseInt(int,10));
}
}
function nthItemOfChunkCount(int) {
const arr = (isArray(this) && this) || arrayFrom(this ?? []);
const idx = parseInt(int,10) - 1;
return (new NthItemOfChunkCount(arr,idx));
}
Object.defineProperty(arrPrototype,'nth',value: nthItemOfChunkCount
});
Object.defineProperty(arrPrototype.nth,{
value: () => 'function nth() { [custom code] }'
});
Object.defineProperty(NthItemOfChunkCount.prototype.of,{
value: () => 'function of() { [custom code] }'
});
// export default Array;
</script>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。