NoDiggityNoDoubt
NoDiggityNoDoubt

Reputation: 521

JS map array of objects to array of objects

I have an API that returns an array of objects(objects represent individual attributes) with individual keys. Objects can have different types and if the object is type 8 or 9 it means it's a multiselect. Multiselect objects look like this:

{
...
type:8
key: attribute6
multiselect_txt: Apple$Carrot$Plum
multiselect_id: 34$13$21
...
}

This would mean that on multiselect the user picked an Apple(id: 34), a Carrot(id: 13) and a Plum(id: 21). So, the text order aligns with the id order and the user picks are seperated by a dollar('$') sign.

My question is, how can I from an array of objects like this:

[
  {
   key: attribute1
   type: 8
   multiselect_txt: Apple$Carrot$Plum
   multiselect_id: 34$13$21
  },
  {
   key: attribute2
   type: 8
   multiselect_txt: Coke$Juice
   multiselect_id: 11$26
  }
]

make an array like this:

[{
  attribute1: [{
    name: 'Apple'
    id: 34
  }, {
    name: 'Carrot'
    id: 13
  }, {
    name: 'Plum'
    id: 21
  }],
}, {
  attribute2: [{
    name: 'Coke'
    id: 11
  }, {
    name: 'Juice'
    id: 26
  }]
}]

Upvotes: 0

Views: 124

Answers (1)

jsN00b
jsN00b

Reputation: 3691

Presented below is one possible way to achieve the desired objective.

Code Snippet

const myTransform = (arr, sep) => (
  arr.map(
    ({
      key,
      multiselect_txt : tx,
      multiselect_id: ids
    }) => ({
      [key]: tx.split(sep).map(
        (name, idx) => ({
          name,
          id: +ids.split(sep)[idx]
        })
      )
    })
  )
);

/* EXPLANATION
// method to transform
// accepts "arr" array and "sep" separator string (like '$')
const myTransform = (arr, sep) => (
  // iterate over "arr"
  arr.map(
    ({
      // destructure to directly access props
      key,
      multiselect_txt : tx,   // rename props to "tx", "ids" for easy usage
      multiselect_id: ids
    }) => ({
      // transform to desired structure
      // key is the value stored in "key"
      // value array is constructed by using ".split()"
      [key]: tx.split(sep).map(
        // the text within "tx" is the name
        (name, idx) => ({
          name,
          // the number within "ids" at corresponding "idx" is the id
          id: +ids.split(sep)[idx]
        })
      )
    })    // implicit return from ".map()"
  )       // implicit return from "myTransform()" method
);
*/

const dataArr = [{
    key: 'attribute1',
    type: 8,
    multiselect_txt: 'Apple$Carrot$Plum',
    multiselect_id: '34$13$21'
  },
  {
    key: 'attribute2',
    type: 8,
    multiselect_txt: 'Coke$Juice',
    multiselect_id: '11$26'
  }
];

console.log(
  'transformed array to:\n',
  myTransform(dataArr, '$')
);
.as-console-wrapper { max-height: 100% !important; top: 0 }

Explanation

Inline comments added to the snippet above.

Upvotes: 2

Related Questions