2

Does anyone know how I can create a new array from existing array with unique joined values from existing array?

const originalArray = [
  [
    { value: 'red', id: 99 },
    { value: 'blue', id: 100 },
  ],
  [
    { value: 'small', id: 101 },
    { value: 'medium', id: 102 },
  ],
  [
    { value: 'modern', id: 103 },
    { value: 'classic', id: 104 },
  ],
];
//
//
const newArrayBasedOnOriginalArray = [
  { value: 'red/small/modern' },
  { value: 'red/small/classic' },
  { value: 'red/medium/modern' },
  { value: 'red/medium/classic' },
  { value: 'blue/small/modern' },
  { value: 'blue/small/classic' },
  { value: 'blue/medium/modern' },
  { value: 'blue/medium/classic' },
];

I calculated that the length of the new array should always be as following:

// length of new array
const lengthOfNewArray = originalArray
  .map((value) => {
    return value.length;
  })
  .reduce((current, old) => {
    return current * old;
  });
//
//
console.log('length of new array:', lengthOfNewArray); // 8

1

3 Answers 3

3

You can do it recursively

const originalArray = [
  [
    { value: 'red', id: 99 },
    { value: 'blue', id: 100 },
  ],
  [
    { value: 'small', id: 101 },
    { value: 'medium', id: 102 },
  ],
  [
    { value: 'modern', id: 103 },
    { value: 'classic', id: 104 },
  ],
];

const getPossibleCombination = (currentValue, arraysRemaining) => {
  if(arraysRemaining.length === 0) return currentValue

  const values = []
  
  const firstArray = arraysRemaining[0]
  
  firstArray.forEach(({value}) => {
    values.push(getPossibleCombination(`${currentValue}/${value}`, arraysRemaining.slice(1, arraysRemaining.length)))
  })
  
  return values.flat()
}

const values = getPossibleCombination('', originalArray)
console.log(values)

Sign up to request clarification or add additional context in comments.

Comments

3

In this case, you do not necessarily need recursion. Array.reduce() greatly does the job:

const originalArray = [
  [
    { value: 'red', id: 99 },
    { value: 'blue', id: 100 },
  ],
  [
    { value: 'small', id: 101 },
    { value: 'medium', id: 102 },
  ],
  [
    { value: 'modern', id: 103 },
    { value: 'classic', id: 104 },
  ],
];

const newArray = originalArray
  .map(elem => elem.map(({value}) => value))
  .reduce((acc, cur) => acc.flatMap(seq => cur.map(part => `${seq}/${part}`)))
  .map(elem => ({value: elem}))

console.log(newArray)

Aside from the initial and final map(), used to simplify the input objects, what I am doing is continuously combining the accumulator with the next sub-array.

For each object in the sub-array I duplicate every object in the accumulator, using the nested map(). flatMap() is used to keep the accumulator flat, with a simple map() the accumulator depth would increase every time we visit a new sub-array.

2 Comments

Your example works really good. However, I tried to make an if statement, if value already exist, then do not return or overwrite the existing value. ``` newArray = [{ value: 'red/small/modern', id: 1, price: 888 }]; ``` So, value "red/small/modern" already exist with price 888, I do not want to overwrite this value and the price. Could you help, to insert somekind of if statement for existing values?
Glad you find it useful, please update the question with the new requirement. Don't forget to put the example and the expected result, thanks
0

First of all if values in each of your arrays is unique then the concatenated values will be unique as well. After you make sure values are unique you can use this code to create combinations of strings:

const newArrayBasedOnOriginalArray = originalArray.reduce(
  (acc, el) =>
    el.flatMap(({ value }) =>
      acc.length ? acc.map((str) => str + "/" + value) : value
    ),
  []
).map(value=>({value});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.