1

I'm working on a coding exercise where my goal is to write a function, named generatePermutations(), in NodeJS that takes a single Object as an argument. Using all Array properties in that object, generate an array of JS objects:

  • Each object is a unique permutation of the values found in property arrays.
  • A property whose value is an empty array can be ignored.
  • If a property in the Object argument is not an array then it should be treated as an array containing a single value.
{
  pilot: ["Han Solo", "Lando Calrissian"],
  copilot: ["Chewbacca", "Rey"],
  ship: "Falcon",
  speed: "1.5c"
}

The function, in this example, should produce the following permutations:

[
  {
    "pilot": "Han Solo",
    "copilot": "Chewbacca",
    "ship": "Falcon",
    "speed": "1.5c"
  },
  {
    "pilot": "Han Solo",
    "copilot": "Rey",
    "ship": "Falcon",
    "speed": "1.5c"
  },
  {
    "pilot": "Lando Calrissian",
    "copilot": "Chewbacca",
    "ship": "Falcon",
    "speed": "1.5c"
  },
  {
    "pilot": "Lando Calrissian",
    "copilot": "Rey",
    "ship": "Falcon",
    "speed": "1.5c"
  }
]

I've been following this: How can I create all combinations of this object's keys/values in JavaScript? but don't fully understand since I can only pass a single argument.

I'm lost on this one and any pointers would be greatly appreciated!

  • Does this answer your question? [Find all permutations of 2 arrays in JS](https://stackoverflow.com/questions/56252742/find-all-permutations-of-2-arrays-in-js) – Hassan Imam Jun 19 '21 at 15:11
  • @HassanImam thank you but not quite the output that I need to solve this one; thanks again! – Sterling Perry Jun 19 '21 at 15:30

2 Answers2

1

You could take a recursive function which separates all key/value pairs and build a new cartesian product by iterating the values, if an array with objects call getCartesian again and build new objects.

function getCartesian(object) {
    return Object.entries(object).reduce((r, [k, v]) => {
        var temp = [];
        r.forEach(s =>
            (Array.isArray(v) ? v : [v]).forEach(w =>
                (w && typeof w === 'object' ? getCartesian(w) : [w]).forEach(x =>
                    temp.push(Object.assign({}, s, { [k]: x }))
                )
            )
        );
        return temp;
    }, [{}]);
}

var data = { pilot: ["Han Solo", "Lando Calrissian"], copilot: ["Chewbacca", "Rey"], ship: "Falcon", speed: "1.5c" };

console.log(getCartesian(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you so so much! I just ran the code snippet this is exactly the output that should be produced. I'm a recursion newb! Any ideas on where to learn more about how solve problems like this? You are a life saver!!!!! – Sterling Perry Jun 19 '21 at 15:33
  • for example take another [answer](https://stackoverflow.com/questions/56972012/how-to-get-the-combination-of-array-values-from-nested-arrays-in-an-array-of-obj/56972231#56972231) with the same function but this answer has a lot more of formatting the answer there. but you can see how the function wotks with simple objects or a little more nested objects. – Nina Scholz Jun 19 '21 at 15:37
  • Many thanks! :) I'm checking this out now. Wishing you all the best! – Sterling Perry Jun 19 '21 at 15:51
0

This is my version of the solution, the result haven't the same order, but the data is permuted 100%.

let data = {
  pilot: ["Han Solo", "Lando Calrissian"],
  copilot: ["Chewbacca", "Rey"],
  ship: "Falcon",
  speed: "1.5c"
};

let newData = new Array();

let currentData = {};

let saveProperty = new Array();

for(let index = 0;index < data.pilot.length; index++){
        for(let property in data){
          
          if(Array.isArray(data[property])){

            if(saveProperty.findIndex(function(e){
                if(e == property){
                    return true;
                }
            }) == -1){

                saveProperty.push(property);
            }
            
            currentData[property] = data[property][index];

          }else{

            currentData[property] = data[property];

          }

        }

        //newData.push(currentData);
    
        

        for(let pr of saveProperty){
            
            data[pr].forEach(function(e, i){

                let copy = {};

                Object.assign(copy,currentData);
                    
                copy[pr] = data[pr][i];


                if(newData.findIndex(function(e){
                    let counter = 0;
                    for(let en in copy){
                        
                        if(copy[en] == e[en]){
                            
                            counter++;
                                                        
                        }

                    }

                    if(counter == Object.keys(copy).length){
                        return true;
                    }
                }) == -1){

                    newData.push(copy);
                }

            });
            
        }

        saveProperty = new Array();

        currentData = {};
    
    

}

console.log(newData);