Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

144
Vistas
Using the Mod Operator for paginating multiple arrays?

I have a number of arrays that I need to pull values from depending on the page that is being requested. Each page needs to be assigned a unique combination of data, so for example:

let numbers = ['One', 'Two']
let fruits  = ['Apples', 'Oranges']
let colours = ['Red', 'Green']
let names   = ['John', 'Jane']

None of the arrays would ever be empty, and so the number of available pages would be the length of all arrays multiplied by each other (so in this case, totalPages would be 16

let totalPages = numbers.length * fruits.length * colours.length * names.length

For every page requested, I need to return a unique set of indices so that every page shows a different group of values, and never more than one from each group.

I currently have nested for-loops (example below) but I was wondering if there's a neater way using the mod operator or something, so that I don't need to rely on the for-loops because at some point I may need to introduce extra arrays and I hate how the nested loops look...

let page = 4 // The requested page (not zero-based index)

let nPage = 1
for(let numberIndex = 0; numberIndex < numbers.length; numberIndex ++) {
    for(let fruitIndex = 0; fruitIndex < fruits.length; fruitIndex ++) {
        for(let colourIndex = 0; colourIndex < colours.length; colourIndex ++) {
            for(let nameIndex = 0; nameIndex < names.length; nameIndex ++) {
                // If the loop iteration matches the requested page,
                // return the combination of indexes as array
                if(page === nPage) {
                    return [numberIndex, fruitIndex, colourIndex, nameIndex]
                }
                nPage ++
            }
        }
    }
}

Thanks in advance for any ideas/suggestions :o)

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

This is really a math/algorithm question (which are always fun!). So a good approach is to see if you can figure out the pattern. E.g., given 3 arrays, [1,2,3,4], [x,y,z], and [11,12], you expect

1 x 11
2 x 11
3 x 11
4 x 11
 
1 y 11
2 y 11
3 y 11
4 y 11
 
1 z 11
2 z 11
3 z 11
4 z 11
 
1 x 12
2 x 12
3 x 12
4 x 12
 
1 y 12
2 y 12
3 y 12
4 y 12
 
1 z 12
2 z 12
3 z 12
4 z 12

The pattern should be clear now, it's just counting, like you count 1,2,3,...9,10,11...99,100,101.... But in traditional counting, all digits start at 0 and wrap at 10. Whereas in our example, the first digit starts at 1 and wraps around at 4; the 2nd digit starts at 'x' and wraps around at 'z', and the 3rd starts at '11' and wraps at 12.

If someone asks you to find the n-th digit (from the right) of the m-th decimal number 4 digits long (e.g. the 3rd digit of 1234 is 2), you could truncate with temp = floor(m / 10 ** (n-1)), which would give you 1234, 123, 12, 1. Then temp % 10 would give the last digit of each: 4, 3, 2, 1.

In our case, our digits aren't base 10, so we replace the 10's with the appropriate calculations:

let numbers = ['1', '2', '3'];
let fruits = ['a', 'b', 'c'];
let colours = ['x', 'y', 'z'];
let names = ['11', '12', '13'];

let getPage = i =>
    [
        numbers[i % numbers.length],
        fruits[Math.floor(i / numbers.length) % numbers.length],
        colours[Math.floor(i / numbers.length / fruits.length) % colours.length],
    ];
  
// print only the first 40 pages, otherwise stackoverflow will truncate the console
for (let i = 0; i < 40; i++)
    console.log(getPage(i).join(' '));

And if you have a dynamic set of arrays (e.g. you don't know ahead of time which of these arrays you will use):

let numbers = ['1', '2', '3'];
let fruits = ['a', 'b', 'c'];
let colours = ['x', 'y', 'z'];
let names = ['11', '12', '13'];

let getPage = (pageI, arrays) => {
    // `pageCounts[i]` is the # of combinations that can generated from the 1st `i` arrays.
    let pageCounts = arrays.map((values, j) => arrays
        .filter((_, k) => k < j)
        .map(a => a.length)
        .reduce((a, b) => a * b, 1));
    return arrays.map((values, j) => values[Math.floor(pageI / pageCounts[j]) % values.length]);
};

// print only the first 40 pages, otherwise stackoverflow will truncate the console
for (let i = 0; i < 40; i++)
    console.log(getPage(i, [numbers, fruits, colours, names]).join(' '));

about 4 years ago · Juan Pablo Isaza Denunciar

0

I find a cartesian generator would work really well here, as it lets you calculate every combination and stop at the n-th value without calculating ahead. Here's an example using an implementation from this answer.

let numbers = ['One', 'Two']
let fruits  = ['Apples', 'Oranges']
let colours = ['Red', 'Green']
let names   = ['John', 'Jane']

let totalPages = numbers.length * fruits.length * colours.length * names.length

// Function from https://stackoverflow.com/a/44338759
function* cartesian(head, ...tail) {
  let remainder = tail.length ? cartesian(...tail) : [[]];
  for (let r of remainder) for (let h of head) yield [h, ...r];
}

function getPage(n) {
    const combinations = cartesian(numbers, fruits, colours, names);
    for (let i = 0; i < (n-1) % totalPages; i++) combinations.next();
    return combinations.next().value;
}

// loops back, so 1 is the same as 17
console.log(getPage(1))
console.log(getPage(17))


On a side note, I would advise you to refactor your code use an array instead of separate variables as it will make it more maintainable.

const pages = [numbers, fruits, colours, names];

const totalPages = pages.length ? pages.reduce((a,b) => a * b.length, 1) : 0;

...

function getPage(n) {
  const combinations = cartesian(...pages);
  ...
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda