有一个包含数据的数组:
const array = [...data]我们必须要有数据类型:
type string
type DataObject {
id: number;
title:string;
}数组中填充了大多数类型的DataObject,但也有一些类型为字符串。
现在,我们必须分块数据,但如果类型是字符串,我们只想分块到1,否则以x数;
如果x=2,这将是我们想要的结果:
const chunkedArray = [["title"], [dataObject, dataObject], [dataObject, dataObject], ["title2"]]我就是不能把这事当回事。每次我认为我找到了解决方案,我就会得到不同的结果。这就是我现在拥有的:
const sliced = newArray.slice(i, i + numColumns);
const titleIndex = sliced.findIndex((a) => typeof a === "string");
if (titleIndex >= 0) {
// Meaning has title
console.log({ titleIndex, i });
for (let a = 0; a < numColumns; a++) {
if (a === titleIndex) {
chunks.push([sliced[a] as any]);
} else {
chunks.push([sliced[a] as any]);
}
}
} else {
chunks.push(sliced);
}
i += numColumns;我得到的是:

我认为现在的问题是,我们正在循环每2次(x=2),我们需要从下一次迭代中将其添加到数组中,但我不知道如何做到这样才能工作。
如果是x=2,但如果x=3或x=4等,则不能这样做:
while (i < n) {
const sliced = newArray.slice(i, i + numColumns);
const titleIndex = sliced.findIndex((a) => typeof a === "string");
if (titleIndex >= 0) {
// Meaning has title
for (let a = 0; a < numColumns; a++) {
if (a === titleIndex) {
chunks.push([sliced[a] as any]);
i += 1;
} else if (a === numColumns - 1) {
chunks.push([sliced[a] as any, ...newArray.slice(i + a, i + a + 1)]);
i += numColumns + 1;
} else {
chunks.push([sliced[a] as any]);
i += 1;
}
}
} else {
chunks.push(sliced);
i += numColumns;
}
}发布于 2022-08-08 13:04:08
我们可以通过将对象存储到缓存数组中来做到这一点,每次输出被填充时,我们都会将该数组推入输出中。
当我们完成迭代时,如果缓存仍然有任何对象(来自不完全组),则将其推送到输出。
看看这个:
第一部分是设置输入数据,我们关心的是splitChunks()
let strings = Array(10).fill('title');
let objects = Array.from({ length: 30 }, () => ({ title: 'title', id: 'id' }));
function shuffle(arr1, arr2) {
if (!arr1.length || !arr2.length) return [...arr1, ...arr2];
return Math.random() > 0.5
? [arr1[0], ...shuffle(arr1.slice(1), arr2)]
: [arr2[0], ...shuffle(arr1, arr2.slice(1))];
}
const data = shuffle(objects, strings);
console.log('Data: ', data);
function splitChunks(data, groupSize) {
let cache = [];
const chunks = data.reduce((acc, val) => {
if (val.title) {
cache.push(val);
if (cache.length === groupSize) {
acc.push(cache);
cache = [];
}
} else {
acc.push(val);
}
return acc;
}, []);
if (cache.length) {
chunks.push(cache);
}
return chunks;
}
let chunks = splitChunks(data, 4);
console.log('Chunks:', chunks);
这种方法可以扩展到更多的数据类型,方法是为每个数据类型添加一个缓存,并在还原器中添加类似的检查。
发布于 2022-08-08 13:31:23
您用
typescript标记标记了您的问题,所以我只能假设类型对您的程序很重要。
考虑以下的职能办法:
在chunkByCount函数中,创建一个result数组作为结果,并为每个对象块创建一个chunk数组。
输入数组的每个元素在循环中一次处理一个:
如果值是字符串:(如果每个字符串指示分块应该重新启动-那么当前块将被推入数组中,如果它有任何对象,并且为下一个组分配一个新的数组给chunk变量)。将字符串值放入数组中,然后将该数组推入结果数组。
如果该值不是字符串:那么它就是您的DataObject对象之一。
当遇到对象时,它会被推入chunk变量的当前数组中。如果(将当前对象推入块后)块的长度等于所需的计数,则将块数组本身推入结果数组,并创建一个新的数组并分配给chunk变量。循环结束后,如果chunk数组中有任何剩余的对象,那么这个块也会被推入结果数组。
type UnchunkedArray<T> = (string | T)[];
type ChunkedArray<T> = ([string] | T[])[];
type DataObject = {
id: number;
title:string;
};
// Generate input array test data:
function createUnchunkedArray ({
groups = 3,
minGroupLength = 7,
maxGroupLength = 10,
} = {}): UnchunkedArray<DataObject> {
let id = 0;
const array: UnchunkedArray<DataObject> = [];
for (let group = 0; group < groups; group += 1) {
array.push(`group ${group}`);
const groupLength = Math.floor(
Math.random()
* (maxGroupLength - minGroupLength + 1)
) + minGroupLength;
for (let i = 0; i < groupLength; i += 1) {
array.push({id, title: `title ${group}-${i}`});
id += 1;
}
}
return array;
}
function chunkByCount (
input: UnchunkedArray<DataObject>,
count: number,
): ChunkedArray<DataObject> {
const result: ChunkedArray<DataObject> = [];
let chunk: DataObject[] = [];
for (const element of input) {
if (typeof element === 'string') {
// If each string indicates that chunking should re-start,
// then use the following code block here. Else, just remove it:
if (chunk.length > 0) {
result.push(chunk);
chunk = [];
}
result.push([element]);
continue;
}
chunk.push(element);
if (chunk.length === count) {
result.push(chunk);
chunk = [];
}
}
if (chunk.length > 0) result.push(chunk);
return result;
}
// Usage example:
console.clear();
const input = createUnchunkedArray();
// Will be 2, 3, or 4:
const chunkCount = Math.floor(Math.random() * 3) + 2;
const chunked = chunkByCount(input, chunkCount);
console.log('Chunk count:', chunkCount);
console.log(chunked);从TS游乐场编译的JavaScript,您可以重复运行,以看到不同的(随机)结果:
"use strict";
// Not used here, but you might find this type useful somewhere in context of the problem:
// type RepeatedTuple<N, T, Tup extends T[] = [T]> = Tup['length'] extends N
// ? Tup
// : RepeatedTuple<N, T, [...Tup, T]>;
// Generate input array test data:
function createUnchunkedArray({ groups = 3, minGroupLength = 7, maxGroupLength = 10, } = {}) {
let id = 0;
const array = [];
for (let group = 0; group < groups; group += 1) {
array.push(`group ${group}`);
const groupLength = Math.floor(Math.random()
* (maxGroupLength - minGroupLength + 1)) + minGroupLength;
for (let i = 0; i < groupLength; i += 1) {
array.push({ id, title: `title ${group}-${i}` });
id += 1;
}
}
return array;
}
function chunkByCount(input, count) {
const result = [];
let chunk = [];
for (const element of input) {
if (typeof element === 'string') {
// If each string indicates that chunking should re-start,
// then use the following code block here. Else, just remove it:
if (chunk.length > 0) {
result.push(chunk);
chunk = [];
}
result.push([element]);
continue;
}
chunk.push(element);
if (chunk.length === count) {
result.push(chunk);
chunk = [];
}
}
if (chunk.length > 0)
result.push(chunk);
return result;
}
// Usage example:
console.clear();
const input = createUnchunkedArray();
// Will be 2, 3, or 4:
const chunkCount = Math.floor(Math.random() * 3) + 2;
const chunked = chunkByCount(input, chunkCount);
console.log('Chunk count:', chunkCount);
console.log(chunked);
https://stackoverflow.com/questions/73277736
复制相似问题