简体   繁体   中英

Finding All Combinations (Cartesian product) of JavaScript array values and then ordering them

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. ie, '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 .

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)

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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