2

I am trying to use the map to change the one of the field name , but I see the order of items are getting changed .

var arrOfObj = [
  {
    name: "test1",
    value: "value1"
  },
  {
    name: "test2",
    value: "value2"
  }
];

function changeKeyName(arr, oldValue, newVal) {
  return arr.map(item => {
    item[`${newVal}`] = item[`${oldValue}`];
    delete item[`${oldValue}`];
    return item;
  });
}

console.log(changeKeyName(arrOfObj, "name", "type"));

Is there any way I can maintain the order of items along with changing of one of the field names.

O/P:

[{type:"test1",value: "value1"}, {type: "test2", value:"value2"}]

Thanks in advance

2 Answers2

1

You can use Object.entries to take an array of entries, then map them, replacing the old key with the new key when found:

var arrOfObj = [
  {
    name: "test1",
    value: "value1"
  },
  {
    name: "test2",
    value: "value2"
  }
];

const changeKeyName = (arr, oldKey, newKey) => arr.map(
  item => Object.fromEntries(
    Object.entries(item).map(
      ([key, val]) => [key === oldKey ? newKey : key, val]
    )
  )
);
console.log(changeKeyName(arrOfObj, "name", "type"));

(Contrary to popular belief, object property order is guaranteed by the specification, and has been implemented in all environments for years. But keep in mind that this will only work for keys which aren't array indicies - array indicies like 0 1 2 can't be ordered relative to other properties, they'll always be iterated over first, in ascending numeric order)

That said, code is generally easier to understand if it's written such that property order doesn't matter - if you have code that depends on the properties being in a particular order, I'd recommend refactoring it so that the property order doesn't matter.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Except for not modifying the original item, this doesn't really change anything in comparison to the OPs code? – Bergi May 18 '20 at 13:33
  • OP's problem is that his `delete` is removing the `name` property from the *first* property in the object and replacing it with a `type` property which is put as the *second* property of the object. He wants `{ type: someVal, value: someVal }`, not `{ value: someVal, type: someVal }` – CertainPerformance May 18 '20 at 13:36
  • @epascarello That only works if `name` is known in advance to be the first property in the object (otherwise, property order gets lost) – CertainPerformance May 18 '20 at 13:38
  • Whoops, I meant to stick that on the OP question, not your answer. lol – epascarello May 18 '20 at 13:49
  • @CertainPerformance Oh. In that case, he shouldn't be using objects at all. – Bergi May 18 '20 at 13:57
  • @CertainPerformance I get this when I try integrating,Property 'fromEntries' does not exist on type 'ObjectConstructor'.Any idea? –  May 18 '20 at 15:19
  • 1
    @li97 You must be using an old IDE or environment that doesn't support `fromEntries` - use [a polyfill](https://www.npmjs.com/package/polyfill-object.fromentries). – CertainPerformance May 18 '20 at 15:20
0

map is being used incorrectly here as you should always return a new set of results from that.

You can do this and you can change the order as required:

const arrOfObj = [
  {
    name: "test1",
    value: "value1"
  },
  {
    name: "test2",
    value: "value2"
  }
];

function changeKeyName(arr, oldValue, newVal) {
  return arr.map(({ [oldValue]: val, ...rest }) => {
    return {
      [newVal]: val,
      ...rest,
    };
  });
}

console.log(changeKeyName(arrOfObj, "name", "type"));
Ryan
  • 5,229
  • 1
  • 20
  • 31
  • This does not result in the property order of the replaced object being maintained, which is the main problem OP is concerned with - you're hard-coding the new property at the start of the object. You also need to use a computed property for `newVal` – CertainPerformance May 18 '20 at 13:40