I have an array of arrays
allArrays = [
['women', 'men'], // gender
['age 18-24', 'age 25-34', 'age 35-44', 'age 45 or over'] // age
]
Further, I want the order of these arrays to be randomized. I shuffle the arrays using Fisher-Yates Shuffle from this answer.
// shuffle array of arrays
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
shuffle(allArrays)
Lastly, I want all the combinations of values. I combine the arrays using the recursive method this answer.
// get all combinations
function allPossibleCases(arr) {
if (arr.length == 1) {
return arr[0];
} else {
var result = [];
var allCasesOfRest = allPossibleCases(arr.slice(1)); // recur with the rest of array
for (var i = 0; i < allCasesOfRest.length; i ) {
for (var j = 0; j < arr[0].length; j ) {
result.push(arr[0][j] ", " allCasesOfRest[i]);
}
}
return result;
}
}
let output = allPossibleCases(allArrays)
However because the order of the initial arrays is randomized the output
is either arranged first by gender or first age. i.e., 'women, age 18-24', 'women, age 25-34', 'women age 35-44', ...
or 'age 18-24, women', 'age 18-24, men', 'age 25-34, women', 'age 25-34, men', ...
The reordering of the string is the intended behavior. However, I am wondering if it is then possible to then arrange the output
array so that the same gender/age are presented in the same position regardless of their initial shuffle. Ideally, the answer would work for n
arrays where n > 1
.
CodePudding user response:
For example, you can sort your output array by age.
let output = ["age 18-24, women", "age 25-34, women", "age 35-44, women", "age 45 or over, women", "age 18-24, men", "age 25-34, men", "age 35-44, men", "age 45 or over, men"]
output.sort((a, b) => {
let ageArr1 = a.match(/(age \d)\w/)
let ageArr2 = b.match(/(age \d)\w/)
if (!ageArr1?.length || !ageArr2?.length) {
return 0
}
let age1 = ageArr1[0].replace('age ', '')
let age2 = ageArr2[0].replace('age ', '')
return age1 - age2
})
console.log(output)
CodePudding user response:
Sort by age and male/female.
let output = ["age 18-24, women", "age 25-34, women", "age 35-44, women", "age 45 or over, women", "age 18-24, men", "age 25-34, men", "age 35-44, men", "age 45 or over, men"]
const getAge = (str) => {
let ageArr = str.match(/(age \d)\w/);
return ageArr?.length ? ageArr[0].replace("age ", "") : 0;
};
output.sort((a, b) => {
let age1 = getAge(a);
let age2 = getAge(b);
let isFemale1 = a.includes("women");
let isFemale2 = b.includes("women");
if (!isFemale1 && isFemale2) {
return 1
} else if (isFemale1 && !isFemale2) {
return -1
}
return age1 - age2;
});
console.log(output);