Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
454 views
in Technique[技术] by (71.8m points)

javascript - How to get the combination of array values from nested arrays in an array of objects

I have an array of objects with the following structure:

 var varientSections = [
  {
    type: "frame",
    values: ["black", "white", "wood"]
  },
  {
    type: "finish",
    values: ["matte", "glossy"]
  }
];

I want to get the combination of the array values and create a new list with it. Right now, I am able to retrieve the combination from the nested array values using the method called getCombination(varientSections). However, I do not know how to create a new list with the following structure:

var results = [
  {
    attributes: [
      {
        type: "frame",
        value: "black"
      },
      {
        type: "finish",
        value: "matte"
      }
    ]
  },
  {
    attributes: [
      {
        type: "frame",
        value: "black"
      },
      {
        type: "finish",
        value: "glossy"
      }
    ]
  },
  {
    attributes: [
      {
        type: "frame",
        value: "white"
      },
      {
        type: "finish",
        value: "matte"
      }
    ]
  },
  {
    attributes: [
      {
        type: "frame",
        value: "white"
      },
      {
        type: "finish",
        value: "glossy"
      }
    ]
  },
  {
    attributes: [
      {
        type: "frame",
        value: "wood"
      },
      {
        type: "finish",
        value: "matte"
      }
    ]
  },
  {
    attributes: [
      {
        type: "frame",
        value: "wood"
      },
      {
        type: "finish",
        value: "glossy"
      }
    ]
  }
];

Below is my code:

function getCombinations(arr) {
  if (arr.length === 0) {
    return [[]];
  }

  let [current, ...rest] = arr;
  let combinations = getCombinations(rest);

  var result = current.values.reduce(
    (accumulator, currentValue) => [
      ...accumulator,
      ...combinations.map(c => [currentValue, ...c])
    ],
    []
  );
  console.log("result is ");
  console.log(result);
  return result;
}

let varientCombinations = getCombinations(varientSections);
console.log(varientCombinations);

let updatedVarientDetails = [];
varientSections.forEach((varientSection, index) => {
  let type = varientSection.type;
  varientCombinations.forEach(combination => {
    let obj = [
      {
        type: type,
        value: combination[index]
      },
    ];
    updatedVarientDetails.push(obj);
  });
});

console.log(updatedVarientDetails);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You could get the cartesian product and give it later the wanted style. The names and values are taken form the handed over object.

The algorithm takes all key/value pairs and has a stric view to the values, that means if an array is found or an object, hence w && typeof w === "object", the actual part is taken an used for adding additional key/value pairs.

For example a small object with two properties

{ a: 1, b: [2, 3] }

yields

[
    { a: 1, b: 2 },
    { a: 1, b: 3 }
]

A bit more advanced object, like

{ a: 1, b: { c: { d: [2, 3], e: [4, 5] } } }

yields the same structure as given

[
    {
        a: 1,
        b: {
            c: { d: 2, e: 4 }
        }
    },
    {
        a: 1,
        b: {
            c: { d: 2, e: 5 }
        }
    },
    {
        a: 1,
        b: {
            c: { d: 3, e: 4 }
        }
    },
    {
        a: 1,
        b: {
            c: { d: 3, e: 5 }
        }
    }
]

Thant means, from any found sub object the cartesian product is taken and combined with the actual values.

const
    getCartesian = object => Object.entries(object).reduce(
        (r, [key, value]) => {
            let temp = [];
            r.forEach(s =>
                (Array.isArray(value) ? value : [value]).forEach(w =>
                    (w && typeof w === "object" ? getCartesian(w) : [w]).forEach(x =>
                        temp.push({ ...s, [key]: x })
                    )
                )
            );
            return temp;
        },
        [{}]
    ),
    data = [{ type: "frame", value: ["black", "white", "wood"] }, { type: "finish", value: ["matte", "glossy"] }],
    result = getCartesian(data)
        .map(o => ({ attributes: Object.assign([], o).map(({ ...o }) => o) }));

console.log(result);

console.log(getCartesian({ a: 1, b: { c: { d: [2, 3], e: [4, 5] } } }));
.as-console-wrapper { max-height: 100% !important; top: 0; }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
...