Home > Blockchain >  Using .map() to iterate over an array of Object values and reassign to new keys
Using .map() to iterate over an array of Object values and reassign to new keys

Time:07-11

I am trying to transform the data below from:

{
      title: 'The Promise',
      blurb: 'Lorem Ipsum',
      cover_image: 'Lorem Ipsum',
      pub_year: 2002,
      genre: 'Foobar'
    }

To:

[
 {
   col1: 'The Promise',
   col2: 'Lorem Ipsum',
   col3: 'Lorem Ipsum',
   col4: 2002
   col5: 'Foobar'
 },
]

I have been puzzling away at this for quite a while and can only get it looking like this, which is just seperate objects rather than a single object as part of an array of objects (there are other book objects in the returned JSON from my db the function needs to churn through)

{col1: 1} //this is an id
{col2: 'The Promise'}
{col3: 'Lorem ipsum'}
{col4: Lorem Ipsum}
{col5: '2002'}
{col6: Foobar}

Here is the code I have been working on:

 const data = React.useMemo(
    () =>
      props.tableData.map((object, i) => {
        Object.values(object).map((value, i) => {
          let col = `col${i   1}`
          const obj = { [col]: value }
        })
      }),
    [props.tableData]
  )

CodePudding user response:

When mapping the values, instead of constructing an object containing a single property, return an entry pair (an array where the first value is the property, and the second value is the associated value) so that you can turn the array of entries into an object with Object.fromEntries.

const data = React.useMemo(
    () =>
        props.tableData.map((object) => (
            Object.fromEntries(
                Object.values(object).map((value, i) => [`col${i   1}`, value])
            )
        )),
    [props.tableData]
);

This depends on the properties in your input objects being ordered. While this is usually dependable, it's not a good thing to rely on, and won't work if any of the properties become numeric (eg 1 or 5). Consider if the input object properties could be formatted as an (ordered) array instead.

CodePudding user response:

It just needed a little tweak. Instead of using map, which returns a new array of mapped elements, use a reducer function to create a new singular object.

const data = {
  title: 'The Promise',
  blurb: 'Lorem Ipsum',
  cover_image: 'Lorem Ipsum',
  pub_year: 2002,
  genre: 'Foobar'
}

function transformIntoColumns(dataToTransform) {
  return Object.keys(dataToTransform).reduce((transformed, prop, index) => {
    transformed[`col${index   1}`] = dataToTransform[prop];
    return transformed;
  }, {});
}

console.log(transformIntoColumns(data));

CodePudding user response:

Another way of achieving this is to use a simple forEach, and the advantage is that you would have one iteration instead of two. Like this:

const data = {
  title: "The Promise",
  blurb: "Lorem Ipsum",
  cover_image: "Lorem Ipsum",
  pub_year: 2002,
  genre: "Foobar"
};
const formatData = () => {
  let result = {};
  Object.values(data).forEach((v, i) => {
    result["column"   Number(i   1)] = v;
  });
  return result;
};

console.log(formatData());

To adapt to your use case:

const data = React.useMemo(() => {
  let result = {};
  Object.values(props.tableData).forEach((v, i) => {
    result["column"   Number(i   1)] = v;
  });
  return result;
}, [props.tableData]);

CodePudding user response:

You could have a mapping object that maps the old keys to the new keys - that way it doesn't matter if they're not in order when you iterate over them.

const mapping={title:"col1",blurb:"col2",cover_image:"col3",pub_year:"col4",genre:"col5"};
const tableData=[{title:"The Promise",blurb:"Lorem Ipsum",cover_image:"Lorem Ipsum",pub_year:2002,genre:"Foobar"}];

const result = tableData.map(obj => {
  const out = {};
  for (const prop in obj) {
    out[mapping[prop]] = obj[prop];
  }
  return out;
});

console.log(result);

  • Related