Mapping some object keys into objects

Viewed 46

I'm trying to transform this object:

url = {
  page: 1,
  limit: 20,
  price_from: 1,
  price_to: 500,
  stock_from: 1,
  stock_to: 200
}

To:

consumableURL = {
  page: 1,
  limit: 20,
  price: {
    price_from: 1,
    price_to: 500,
  },
  stock: {
    stock_from: 1,
    stock_to: 200
  }
}

How is this achievable, in a reusable manner to account for other possible introduced keys in the feature?

And I'm guessing also with validation to make sure the two pairs exist before mapping them into an object?

2 Answers

You can split and check the result count to make the decision about the nested props.

const url = {
  page: 1,
  limit: 20,
  price_from: 1,
  price_to: 500,
  stock_from: 1,
  stock_to: 200
};

const res = Object.entries(url).reduce((obj, [k, v]) => {
  const splitArr = k.split('_');
  if (splitArr.length > 1) {
    obj[splitArr[0]] = obj[splitArr[0]] || {};
    obj[splitArr[0]][k] = v
  } else
    obj[k] = v;
  return obj;
}, {})

console.log(res)


If it's going to be nested then you can use recursion or a nested loop. Here I'm using a nested reduce which will iterate over the split array to generate the deeply nested values.

const url = {
  page: 1,
  limit: 20,
  price_from: 1,
  price_to: 500,
  stock_from: 1,
  stock_to: 200,
  stock_abc_to: 200,
  
};

const res = Object.entries(url).reduce((obj, [k, v]) => {
  const splitArr = k.split('_');
  splitArr.slice(0, -1).reduce((o, key) => o[key] = o[key] || {}, obj)[k] = v
  return obj;
}, {})

console.log(res)

I think a following can be a possible solution with .reduce():

const url = {
  page: 1,
  limit: 20,
  price_from: 1,
  price_to: 500,
  stock_from: 1,
  stock_to: 200
};

const keys = ['price', 'stock'];

const entries = Object.entries(url);
const consumableURL = entries.reduce((a, [k, v]) => {
  const contains = keys.some(e => k.indexOf(e) !== -1);

  if (!contains) {
    return {...a, [k]: v};
  } else {
    const prop = k.split('_')[0];
    return { ...a, [prop]: { ...a[prop], [k]: v } };
  }
}, {});

console.log(consumableURL);

Or in a shorter way which does not help the readability but works:

const url = { page: 1, limit: 20, price_from: 1, price_to: 500, stock_from: 1, stock_to: 200 };
const keys = ['price', 'stock'];
const entries = Object.entries(url);
const consumableURL = entries.reduce((a, [k, v]) => !keys.some(e => k.indexOf(e) !== -1) ? {...a, [k]: v} : { ...a, [k.split('_')[0]]: { ...a[k.split('_')[0]], [k]: v } }, {});
console.log(consumableURL);

I hope that helps!

Related