怎样才能达到以下效果?在输入数字5和以下数组时:
const list = ['a', 'b', 'c'];
它应该产生以下输出:
['a', 'b', 'c', 'a', 'b'] // Total 5
我尝试了for和while,但我不知道当循环超过列表长度时如何重新启动循环。
qgzx9mmu1#
计算整个列表重复多少次才能有足够的元素; do that repetition using Array.fill and .flat;然后truncate using .slice。
Array.fill
.flat
.slice
function repeatToLength(source, size) { const iterations = Math.ceil(size / source.length); return Array(iterations).fill(source).flat().slice(0, size); } console.log(repeatToLength(['a', 'b', 'c'], 5));
szqfcxe22#
您可以通过从起始列表(下面的baseList)中重复添加项目,直到达到所需的长度。你可以通过使用模运算符(%)来获得基列表中的正确索引,以获得输出列表的长度除以基列表的长度的余数,例如:
baseList
%
outputLength % baseLength == indexIntoBaseList 0 % 3 == 0 1 % 3 == 1 2 % 3 == 2 3 % 3 == 0 4 % 3 == 1 5 % 3 == 2
这为您的基本列表提供了一个重复的索引模式,您可以使用它来添加正确的项。
function RepeatListToLength(baseList, maxLength) { var output = []; while(output.length < maxLength) { output.push(baseList[output.length % baseList.length]); } return output; } console.log(RepeatListToLength([1,2,3,4,5], 13));
csbfibhn3#
这是一个递归的变体。repeatToLength函数用一个由两个旧数组组成的新数组调用自己,直到它达到足够的长度,然后将最终数组切片到所需的确切长度:
const repeatToLength = (arr, len) => arr.length < len ? repeatToLength([...arr, ...arr], len) : arr.slice(0, len); console.log(repeatToLength(['a', 'b', 'c'], 5));
在我的递归解决方案和Karls之间做了一些速度测试之后,我想我又给予了一次,写了一个版本,创建一个大的空数组,然后使用原始数组和模运算符Map它。(我从尼克的答案中偷了模数的概念。)它比Chrome中的递归解决方案稍微快一点,在Firefox中更快一点(在Firefox中仍然没有击败Karls解决方案的速度):
const repeatToLength = (arr, len) => [...new Array(len)] .map((x, i) => arr[i % arr.length]); console.log(repeatToLength(['a', 'b', 'c'], 5));
我的在Chrome中似乎要快一些,但Karls在Firefox中稍快一些(MacOS -最新浏览器版本,2023年5月)。
const thomas = (arr, len) => arr.length < len ? thomas([...arr, ...arr], len) : arr.slice(0, len); function karl(source, size) { const iterations = Math.ceil(size / source.length); return Array(iterations).fill(source).flat().slice(0, size); } const thomas2 = (arr, len) => [...new Array(len)] .map((x, i) => arr[i % arr.length]); function time(func, args, runNumberOfTimes) { let start = performance.now(); for (let i = 0; i < runNumberOfTimes; i++) { func(...args); } return Math.round(performance.now() - start) + ' ms'; } let args; console.log('Small array big repeat, run 2,000 times each'); args = [[1, 2, 3, 4, 5], 10000]; console.log('Array size: 5, make an array 10,000 items long.'); console.log('Karls solution', time(karl, args, 2000)); console.log('Thomas solution', time(thomas, args, 2000)); console.log('Thomas2 solution', time(thomas2, args, 2000)); console.log('\nBig array, smaller repeat, run 100 times each'); console.log('Array size: 10,000, make an array 100,000 items long'); args = ['x'.repeat(10000).split(''), 100000]; console.log('Karls solution', time(karl, args, 100)); console.log('Thomas solution', time(thomas, args, 100)); console.log('Thomas2 solution', time(thomas2, args, 100));
3条答案
按热度按时间qgzx9mmu1#
计算整个列表重复多少次才能有足够的元素; do that repetition using
Array.fill
and.flat
;然后truncate using.slice
。szqfcxe22#
您可以通过从起始列表(下面的
baseList
)中重复添加项目,直到达到所需的长度。你可以通过使用模运算符(
%
)来获得基列表中的正确索引,以获得输出列表的长度除以基列表的长度的余数,例如:这为您的基本列表提供了一个重复的索引模式,您可以使用它来添加正确的项。
csbfibhn3#
这是一个递归的变体。repeatToLength函数用一个由两个旧数组组成的新数组调用自己,直到它达到足够的长度,然后将最终数组切片到所需的确切长度:
我的第二个解决方案
在我的递归解决方案和Karls之间做了一些速度测试之后,我想我又给予了一次,写了一个版本,创建一个大的空数组,然后使用原始数组和模运算符Map它。(我从尼克的答案中偷了模数的概念。)
它比Chrome中的递归解决方案稍微快一点,在Firefox中更快一点(在Firefox中仍然没有击败Karls解决方案的速度):
速度对比:我的两个算法和卡尔斯
我的在Chrome中似乎要快一些,但Karls在Firefox中稍快一些(MacOS -最新浏览器版本,2023年5月)。