繁体   English   中英

返回一个由另一个数组中的迭代值填充的 N 个元素的新数组的简洁方法? 原生 JavaScript

[英]Concise way to return a new array of N elements filled with iterated values from another array? Vanilla JavaScript

我有一个给定的元素数量不确定的数组,该数组可以是数字或字符串,然后我需要生成一个由第一个数组的迭代元素组成的 N 个元素的新数组

我已经有一个函数可以做到这一点,但它只适用于原始数组是连续数字,它不适用于字符串。 关于如何实现它,我有无数的想法。 我可以将数组连接到一个新的数组,直到它等于或大于所需的元素数量,然后将新的数组长度设置为所需的数量,但是有没有更简洁优雅的方法来做到这一点?

IDEA 01代码笔

 function populateArray(qty) { // Array to populate from let array = [1,2,3]; //Determine the Range Length of the array and assign it to a variable let min = array[0]; let max = array[array.length - 1]; const rangeLength = (max - min + 1); //Initialize uniqueArray which will contain the concatenated array let uniqueArray = []; //Test if quantity is greater than the range length and if it is, //concatenate the array to itself until the new array has equal number of elements or greater if (qty > rangeLength) { //Create an array from the expansion of the range let rangeExpanded = Array.from(new Array(rangeLength), (x,i) => i + min); while (uniqueArray.length < qty) { uniqueArray = uniqueArray.concat(rangeExpanded); } } // Remove additional elements uniqueArray.length = qty return uniqueArray; } console.log(populateArray(13))

IDEA 02 codepen ,但它用整个原始数组填充新数组 13 次,而不是迭代项

 // FILL A NEW ARRAY WITH N ELEMENTS FROM ANOTHER ARRAY let array = [1,2,3]; let length = 13; let result = Array.from( { length }, () => array ); console.log(result);

预期结果为 [1,2,3,1,2,3,1,2,3,1,2,3,1] 如果原始数组由字符串组成,则预期结果为 [dog,cat,sheep ,狗,猫,羊,狗,猫,羊,狗,猫,羊,狗]

您可以稍微调整您的第二个想法 - 计算您需要重复初始数组的次数以得出所需的总项目数,然后将其展.slice

 let array = [1,2,3]; let length = 13; const fromLength = Math.ceil(length / array.length); let result = Array.from( { length: fromLength }, () => array ) .flat() .slice(0, length); console.log(result);

您可以使用生成器函数从输入创建重复序列。 您可以为生成的序列添加一个限制,并将其简单地转换为一个数组:

 function* repeatingSequence(arr, limit) { for(let i = 0; i < limit; i++) { const index = i % arr.length; yield arr[index]; } } const generator = repeatingSequence(["dog", "cat", "sheep"], 10); const result = Array.from(generator); console.log(result);

或者,您可以创建一个没有限制的无限重复序列,然后为数组生成任意数量的元素:

 function* repeatingSequence(arr) { let i = 0 while(true) { const index = i % arr.length; yield arr[index]; i++; } } const generator = repeatingSequence(["dog", "cat", "sheep"]); const result = Array.from({length: 10}, () => generator.next().value); console.log(result);

我会选择@CertainPerformance 的回答。 但这是一种不同的方法,只是为了开箱即用的目的

// A function for getting an index up to length's size 
function getIDX(idx, length){
return idx <= length ? idx : getIDX(idx-length, length); 
}


const newArrayLength = 13;
const sourceArray = [1,2,3];
const resultArray = [];
for(let i=0; i< newArrayLength; i++){
resultArray[i]=sourceArray[getIDX(i+1, sourceArray.length)-1];
}

编辑 1 :我正在比较这种方法与此处描述的其他方法的性能,似乎如果您想创建一个非常大的新数组(例如:newArrayLength= 10000), getIDX()函数需要花费很多时间才能完成,因为调用堆栈的大小。 所以我通过删除递归改进了getIDX()函数,现在复杂度是 O(1) 检查一下:

function getIDX(idx, length){
if (length === 1) {return idx};
const magicNumber = length * (Math.ceil(idx/length)-1);
 return idx - magicNumber;
}

使用新的getIDX()函数,这种方法似乎是最getIDX() 您可以在此处查看测试: https : //jsbench.me/v7k4sjrsuw/1

您可以使用modulo运算符。 特别感谢@Vlaz的缩短版本:

Array.from({ length:length }, (e, i) => array[ i  % array.length ])

一个例子:

 let array = [1,2,3]; let length = 13; const result = Array.from({ length:length }, (e, i) => array[ i % array.length ]); console.log(result);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM