I have several arrays with different lengths that I'm going to loop through. Example:
Array1 = ['item', 'item', 'item', 'item']
Array2 = ['item', 'item', 'item', 'item', 'item', 'item', 'item', 'item']
Array3 = ['item', 'item', 'item', 'item', 'item']
Array4 = ['item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item', 'item']
If the array length is less than for example 10, I want to duplicate the items in the array, but only until the maximum number is met. I don't want to loop more than necessary.
How can I do this? I'm working in javascript now, but I guess it's more of a math question :)
CodePudding user response:
As I understand it, you have a series of arrays with varying lengths, and you want to loop through an arbitary sequence, say 0 <= n < max
, and use an item from each of the arrays at index n
but wrapping around to the beginning if the array has too few elements to supply one for index n
.
If so, you can use the remainder operator to determine the array index to use for any given array: n % array.length
. For instance:
0 % 3 is 0 1 % 3 is 1 2 % 3 is 2 3 % 3 is 0 -- wrapped around! 4 % 3 is 1 5 % 3 is 2 6 % 3 is 0 -- wrapped around again!
Here's an example going from 0-9 on arrays that have varying lengths (two of them have fewer than 10 elements, one of them has more):
const array1 = [1, 2, 3];
const array2 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
const array3 = ["A", "B", "C", "D", "E"];
const maximum = 10;
for (let n = 0; n < maximum; n) {
const a = getItem(array1, n); // Or just array1[n % array1.length]
const b = getItem(array2, n); // Or just array2[n % array2.length]
const c = getItem(array3, n); // Or just array3[n % array3.length]
console.log(n, ":", a, b, c);
}
// I've used a function because it would be *really* easy if just
// doing it inline to use `someArray[n % someOtherArray.length`
// and wind up with a bug in the code
function getItem(array, n) {
const index = n % array.length;
return array[index];
}
.as-console-wrapper {
max-height: 100% !important;
}
CodePudding user response:
If you are okay with creating a new array, then you could use Array.from()
to get an array of a target length and then use the %
operator to cycle through the given array.
const fill = (array, target) =>
Array.from({ length: target }, (_, i) => array[i % array.length])
const array1 = [1, 2, 3],
array2 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
const fill = (array, target) =>
Array.from({ length: target }, (_, i) => array[i % array.length])
console.log(...fill(array1, 10) )
console.log(...fill(array2, 10) )
If you want to mutate the array, then you can repurpose the above code to use splice
and push
based on whether the given array is bigger than the target length or not.
const fillWithMutation = (array, target) => {
const { length } = array;
if (length >= target)
array.splice(target)
else
array.push(
...Array.from({ length: target - length }, (_, i) => array[i % length])
)
return array
}
const array1 = [1, 2, 3],
array2 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"],
excatly10 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const fillWithMutation = (array, target) => {
const { length } = array;
if (length >= target)
array.splice(target)
else
array.push(
...Array.from({ length: target - length }, (_, i) => array[i % length])
)
return array
};
[array1, array2, excatly10].forEach(arr => fillWithMutation(arr, 10))
console.log(...array1)
console.log(...array2)
console.log(...excatly10)