yurii
yurii

Reputation: 193

Modifying an array with objects

I have an array of objects each object has one nested object I need to modify that

Example: What I have below

const array = [{
    asset: {key: '1235', type: 'mocFirst'},
    id: 27,
    marketValuey: 6509,
    marketValueySecond: 65033,
    marketValueyThird: 650900,
}]

I want get that:

const array = [{
    type: 'mocFirst'
    key: '1235',
    id: 27,
    marketValuey: 6509,
    marketValueySecond: 65033,
    marketValueyThird: 650900,
}]

There is my solution

const array = [{
    asset: {key: '1235', type: 'mocFirst'},
    id: 27,
    marketValuey: 6509,
    marketValueySecond: 65033,
    marketValueyThird: 650900,
},
    {
        asset: {key: '12', type: 'mocFirst44'},
        id: 27,
        marketValuey: 6409,
        marketValueySecond: 64033,
        marketValueyThird: 640900,
    },
    {
        asset: {key: '1299', type: 'mocFirst'},
        id: 271,
        marketValuey: 6109,
        marketValueySecond: 61033,
        marketValueyThird: 610900,
    },
    {
        asset: {key: '1296', type: 'mocFirst'},
        id: 272,
        marketValuey: 65092,
        marketValueySecond: 650332,
        marketValueyThird: 6509020,
    },

]

    const resultArr = array.map(item => {
    const { asset, ...newObj} = item;
    const { key, type } = item.asset;
    return { key, type, ...newObj};

});

Any things about my solution? Maybe it can be done better? In production, I will have a big array

Upvotes: 0

Views: 83

Answers (6)

Sourav Suman
Sourav Suman

Reputation: 23

I would use a concept of destructuring.

array.map((elem) => {
 const {
    id, 
    marketValuey, 
    marketValueySecond, 
    marketValueyThird, 
    asset: {key}, 
    asset: {type}
 } = elem;
 
 return {
  id,
  marketValuey, 
  marketValueySecond, 
  marketValueyThird, 
  key, 
  type
  }
})

for more detailed concept of destructuring refer - nested-destructuring

Upvotes: 1

Jake Cronin
Jake Cronin

Reputation: 1062

I like this solution, which I found by searching for "flatten nested object in javascript".

Here is the code in action from my favorite answer:

const crushObj = (obj = {}) => Object.keys(obj || {}).reduce((acc, cur) => {
  if (typeof obj[cur] === 'object') {
    acc = { ...acc, ...crushObj(obj[cur])}
  } else { acc[cur] = obj[cur] }
  return acc
}, {})

const obj = {
  a:2,
  b: {
    c:3
  }
}

const output = crushObj(obj)
console.log(output)
// { a: 2, c: 3 }

It would be great for a library like Lodash to offer support for this.

Upvotes: 1

Alessio Cantarella
Alessio Cantarella

Reputation: 5201

If you just need to transform asset.key and asset.type respectively into key and type, and you want to increase performance, manual assignment of fields is around 4-5 times faster than your solution.
e.g. I have created an array with 1000 items to compare your solution (which takes around 2.5 ms to create array1) with mine (around 0.5 ms to create array2).

const N = 1000;
let array = [];
for (let i = 0; i < N; i++) {
  let random_item = {
    asset: {
      key: Math.random(N),
      type: 'mocFirst'
    },
    id: Math.random(N),
    marketValuey: Math.random(N),
    marketValueySecond: Math.random(N),
    marketValueyThird: Math.random(N)
  };
  array.push(random_item);
}

const t0 = performance.now();
const array1 = array.map(item => {
  const {
    asset,
    ...newObj
  } = item;
  const {
    key,
    type
  } = item.asset;
  return {
    key,
    type,
    ...newObj
  };
});
console.log(array1[10]);
const t1 = performance.now();
console.log(`Operation took ${t1 - t0} milliseconds.`);

let array2 = [];
for (let i = 0; i < array.length; i++) {
  array2.push({
    key: array[i].asset.key,
    type: array[i].asset.type,
    id: array[i].id,
    marketValuey: array[i].marketValuey,
    marketValueySecond: array[i].marketValueySecond,
    marketValueyThird: array[i].marketValueyThird,
  });
}
console.log(array2[10]);
const t2 = performance.now();
console.log(`Operation took ${t2 - t1} milliseconds.`);

Upvotes: 1

Ovidijus Parsiunas
Ovidijus Parsiunas

Reputation: 2732

The only speed-up that you can 'potentially' introduce is via the use of a for loop instead of a map method. This does unfortunately depend on how the compiler will optimize your code and the effects will only become noticeable if you are working with very large arrays. Benchmarking can be referenced here.

The final part of your code should look like this:

const resultArr = [];
for (let i = 0; i < array.length; i += 1) {
  const { asset, ...newObj} = array[i];
  const { key, type } = asset;
  resultArr.push({ key, type, ...newObj});
}

It is important to understand that the speedup of this code will not be very noticeable and developers usually prefer more obvious/maintainable syntax, so your original answer can be considered correct. Hence, use this at your own discretion.

Upvotes: 1

Sir Archibald Humphrey
Sir Archibald Humphrey

Reputation: 339

Just flatten it out like so:

var outArr = array.map(item => {
   // Create the new items
   item.key = item.asset.key
   item.type = item.asset.item
   // Delete the old parent
   delete item.asset
   return item
})

Upvotes: 1

Vivek Sharma
Vivek Sharma

Reputation: 553

Here you go, it's a recursive solution to flatten the object

function flat(source, target) {
  Object.keys(source).forEach(function(k) {
    if (source[k] !== null && typeof source[k] === 'object') {
      flat(source[k], target);
      return;
    }
    target[k] = source[k];
  });
}

const array = [{
    asset: {
      key: '1235',
      type: 'mocFirst'
    },
    id: 27,
    marketValuey: 6509,
    marketValueySecond: 65033,
    marketValueyThird: 650900,
  },
  {
    asset: {
      key: '12',
      type: 'mocFirst44'
    },
    id: 27,
    marketValuey: 6409,
    marketValueySecond: 64033,
    marketValueyThird: 640900,
  },
  {
    asset: {
      key: '1299',
      type: 'mocFirst'
    },
    id: 271,
    marketValuey: 6109,
    marketValueySecond: 61033,
    marketValueyThird: 610900,
  },
  {
    asset: {
      key: '1296',
      type: 'mocFirst'
    },
    id: 272,
    marketValuey: 65092,
    marketValueySecond: 650332,
    marketValueyThird: 6509020,
  },

]
let flatArr = array.map(item => {
  let flatObj = {};
  flat(item, flatObj);
  return flatObj
});
console.log(flatArr);

Upvotes: 4

Related Questions