16

I have

var tab = {
abc:1,
def:40,
xyz: 50
}

I want to change the name of abc,def, xyz to something else, is it possible?

I tried

const test = Object.keys(tab).map(key => {
  if (key === 'abc') {
    return [
      a_b_c: tab[key]
    ]
  }
});

console.log(test);

I got many undefined keys.

Alan Jenshen
  • 3,159
  • 9
  • 22
  • 35
  • Sure you do - your `map` callback only `return`s anything when `key === 'abc'`, and will return `undefined` else. What did you expect? – Bergi May 08 '17 at 03:44
  • 1
    Actually that should throw a syntax error. Array literals don't have properties. – Bergi May 08 '17 at 03:45
  • 1
    Is the question "How do I rename object properties?", or "How do I rename object properties *with `Object.keys()`*?" Anyway, you can't rename a property, you have to add a new property and delete the old one. Or build a new object with the key names that you want. – nnnnnn May 08 '17 at 03:51
  • @nnnnnn I don;'t know, as long as it worked, I mentioned object.keys() because that's what in my mind first. Basically I want to normalize or change the object key's names. – Alan Jenshen May 08 '17 at 03:52
  • @Bergi so what's the solution? – Alan Jenshen May 08 '17 at 03:54
  • 1
    [Renaming object keys](http://stackoverflow.com/questions/4647817/javascript-object-rename-key). By the way, what if another property already exists with the new name? – nnnnnn May 08 '17 at 03:55
  • @nnnnnn I rather build a new set of array than doing those over complicated stuff, what do you think? – Alan Jenshen May 08 '17 at 03:57
  • @AlanJenshen So what's the expected output? – Bergi May 08 '17 at 04:00

11 Answers11

18

Here is the full code for replacing keys based on object that maps the values to replace:

const tab = {abc: 1, def: 40, xyz: 50};
const replacements = {'abc': 'a_b_c', 'def': 'd_e_f'};

let replacedItems = Object.keys(tab).map((key) => {
  const newKey = replacements[key] || key;
  return { [newKey] : tab[key] };
});

This will output an array with three objects where keys are replaced. If you want to create a new object out of them, just:

const newTab = replacedItems.reduce((a, b) => Object.assign({}, a, b));

This outputs: {"a_b_c": 1, "d_e_f": 40, "xyz": 50}

Samuli Hakoniemi
  • 18,740
  • 1
  • 61
  • 74
  • `Object.assign({}, ...replacedItems)` should do as well. And don't forget to pass an initial argument to `reduce`! – Bergi May 08 '17 at 04:12
6

Here's how I solved it. I used a map to map between existing key and new key. Just substitute the map with whatever new values you need. Finally remove old keys from the object using omit.

var tab = {
  abc:1,
  def:40,
  xyz: 50
}

var map = {
    abc : "newabc",
    def : "newdef",
    xyz : "newxyz"
}


_.each(tab, function(value, key) {
    key = map[key] || key;
    tab[key] = value;
});


console.log(_.omit(tab, Object.keys(map)));
Engineer
  • 8,529
  • 7
  • 65
  • 105
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
6

With lodash mapKeys function its quite easy to transform object keys.

let tab = {
  abc: 1,
  def: 40,
  xyz: 50
}

const map = {
  abc: "newabc",
  def: "newdef",
  xyz: "newxyz"
}

// Change keys
_.mapKeys(tab, (value, key) => {
  return map[value];
});

// -> { newabc: 1, newdef: 40, newxyz: 50 }
Mohan Dere
  • 4,497
  • 1
  • 25
  • 21
5

Here is a way to do it with deconstructing assignment and arrow functions.

const rename = (({abc: a_b_c, ...rest}) => ({a_b_c, ...rest}))
console.log(rename({abc: 1, def: 2}))
// { "a_b_c": 1, "def": 2 }
Clemens
  • 1,302
  • 2
  • 15
  • 12
3

UPDATE: Sorry for the syntax errors; corrected and verified in browser console.

Shortest way I've found so far:

let tab = {abc: 1, def: 40, xyz: 50};

const {abc: a_b_c, def: d_e_f, ...rest} = tab;
tab = {a_b_c, d_e_f, ...rest}  
// { "a_b_c": 1, "d_e_f": 40, "xyz": 50}
Jeff Lowery
  • 2,492
  • 2
  • 32
  • 40
2

That's easy with lodash.

import { mapKeys } from 'lodash';    

const tab = {
    abc: 1,
    def: 40,
    xyz: 50
};

const test = mapKeys(tab, (value, key) => {
    if (key === 'abc') return 'a_b_c';
    return key;
});
1

A really easy way to change the keys dynamically without having to map the new key values could work like this :

const tab = { abc: 1, def: 40, xyz: 50 };
const changeString = (s) => s.split('').join('_');

Object.entries(tab).reduce((acc, [k, v]) => ({ ...acc, [changeString(k)]: v }), {})

// Output: {a_b_c: 1, d_e_f: 40, x_y_z: 50}

It uses Object.entries but you can easily swap it over to Object.keys like this:

Object.keys(tab).reduce((acc, k) => ({ ...acc, [changeString(k)]: tab[k] }), {})

Advanced: Nested objects

If you have nested objects and want to cycle through all the keys, you could try this:

const changeString = (s) => s.split('').join('_');
const isArray = (a) => Array.isArray(a);
const isObject = (o) => o === Object(o) && !isArray(o) && typeof o !== 'function';

const keyChanger = (o) => {
  if (isObject(o)) {
    return Object.entries(o).reduce((acc, [k, v]) => ({ ...acc, [changeString(k)]: keyChanger(v) }), {})

  } else if (isArray(o)) {
    return o.map((i) => keyChanger(i));
  }

  return o;
};

And you call it by simply doing this:

const tab2 = { abc: 1, def: 40, xyz: { hij: 12, klm: [{ nop: 43 }, { qrs: 65 }]}}

keyChanger(tab2)

// Output: { a_b_c: 1, d_e_f: 40, x_y_z: { h_i_j: 12, k_l_m: [{ n_o_p: 43 }, { q_r_s: 65 }]}}

8bithero
  • 1,474
  • 1
  • 18
  • 23
0

You can add the new key and delete the old one.

var tab = {
abc:1,
def:40,
xyz: 50
}

    var key = 'abc'
    console.log(key)
    tab['a_b_c'] = tab[key]
    delete tab[key]
    
 
console.log(tab);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
0

you can use ES6 destructuring for it. For example, you can do something like this:

let sample = {a:1,b:2,c:3}
let {a:pippo,...rest} = sample
sample={pippo,...rest}
7laria
  • 44
  • 3
0

const countries = [
    {"id": 1, "name": "Afghanistan"},
    {"id": 2, "name": "Albania"},
    {"id": 3, "name": "Algeria"},
    {"id": 4, "name": "American Samoa"}
];
const transformed = countries.map(({ id, name }) => ({ label: id, value: name }));
console.log(transformed);
Nhat Nguyen
  • 410
  • 1
  • 7
  • 7
-1

hope this will help

initial data:

let tab = {
    abc: 1,
    def: 40,
    xyz: 50
};

new key mappings:

let newKeyMappings = {
    abc: 'cab',
    def: 'fed',
    xyz: 'zyx'
};

mapping values with new keys

let mapped = Object.keys(tab).map(oldKey=> {
    let newKey = newKeyMappings[oldKey];
    let result ={};
    result[newKey]=tab[oldKey];
    return result;
});

since mapped contains array of mapped object apply reduce operator

let result = mapped.reduce((result, item)=> {
    let key = Object.keys(item)[0];
    result[key] = item[key];
    return result;
}, {});
Roshane Perera
  • 132
  • 1
  • 6