2

I need help to find all combined possibilities from a tree

I readed a lot of documentation about cartesian product, tried a lot of things but none of them seems to work properly...

This is my tree

var data = [
  {
    "id": 5,
    "name": "Support papier",
    "type": "filter",
    "children": [
      {
        "id": 24,
        "name": "60 g/m² papier mat",
        "type": "value",
        "children": []
      },
      {
        "id": 7,
        "name": "90 g/m² papier couché",
        "type": "value",
        "children": [
          {
            "id": 8,
            "name": "Propriété papier",
            "type": "filter",
            "children": [
              {
                "id": 18,
                "name": "Papier mat",
                "type": "value",
                "children": [],
              },
              {
                "id": 60,
                "name": "Papier brillant",
                "type": "value",
                "children": [],
              }
            ]
          }
        ],
      }
    ]
  }
]

And this is my expected result :

[
  [
    {id: 5, name:"support papier", type: "filter"}, 
    {id: 24, name:"60 g/m² papier mat", type: "value"},

  ],
  [
    {id: 5, name:"support papier", type: "filter"}, 
    {id: 7, name:"90 g/m² papier mat", type: "value"},
    {id: 8, name:"Propriété papier", type: "filter"}, 
    {id: 18, name:"Papier mat", type: "value"},
  ],
  [
    {id: 5, name:"support papier", type: "filter"}, 
    {id: 7, name:"90 g/m² papier mat", type: "value"},
    {id: 8, name:"Propriété papier", type: "filter"}, 
    {id: 60, name:"Papier brillant", type: "value"},
  ]
]

Of course, every empty array can be populated... :)

Thx for your help :)

1 Answers1

1

You could get each level and map the next lower level to the result set.

Now, what is it doing?

The first part of collecting data is just getting all nodes to the end of the children's objects.

The other part is using a cartesian product for children which object has

type === 'value'

This works in two steps

  1. Collect all items by getting the data and map these items with the actual object.

  2. Create a cartesian product from an array of items.

The rest is just either pushing a new array with parts and adding the actual object (without children) or if no children are available, only the actual object in an array.

function getData(array) {
    return array.reduce((r, { children, ...o }) => {
        if (children.length) {
            var parts = o.type === 'value'
                    ? children
                        .map(({ children = [], ...p }) => getData(children).map(q => [p, ...q]))
                        .reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []))
                    : getData(children);

            r.push(...parts.map(q => [o, ...q]));
        } else {
            r.push([o]);
        }
        return r;
    }, []);
}

var data = [{ id: 5, name: "Support papier", type: "filter", children: [{ id: 24, name: "60 g/m² papier mat", type: "value", children: [{ id: 9, name: "Finition", type: "filter", children: [{ id: 19, name: "Sans finition", type: "value", children: [] }, { id: 20, name: "Vernis anti UV", type: "value", children: [] }] }, { id: 8, name: "Propriété papier", type: "filter", children: [{ id: 60, name: "Papier brillant", type: "value", children: [] }, { id: 18, name: "Papier mat", type: "value", children: [] }] }] }, { id: 7, name: "90 g/m² papier couché", type: "value", children: [{ id: 8, name: "Propriété papier", type: "filter", children: [{ id: 18, name: "Papier mat", type: "value", children: [] }, { id: 60, name: "Papier brillant", type: "value", children: [] }] }] }] }],
    result = getData(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Community
  • 1
  • 1
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324