admin管理员组

文章数量:1128021

I have an extremely large JSON object structured like this:

{A : 1, B : 2, C : 3, D : 4}

I need a function that can swap the values with keys in my object and I don't know how to do it. I would need an output like this:

{1 : A, 2 : B, 3 : C, 4 : D}

Is there any way that I can do this would manually created a new object where everything is swapped?
Thanks

I have an extremely large JSON object structured like this:

{A : 1, B : 2, C : 3, D : 4}

I need a function that can swap the values with keys in my object and I don't know how to do it. I would need an output like this:

{1 : A, 2 : B, 3 : C, 4 : D}

Is there any way that I can do this would manually created a new object where everything is swapped?
Thanks

Share Improve this question edited Sep 7, 2021 at 23:33 pilchard 12.9k5 gold badges12 silver badges26 bronze badges asked Apr 11, 2014 at 13:11 C1DC1D 3,2042 gold badges23 silver badges20 bronze badges 4
  • 1 are all values numbers and do the numbers repeat? If the values repeat then you wont be able to swap them as they will overwrite the others, unless you change their value to some unique value. There might be a better solution what is the reason for needing the swap? – Patrick Evans Commented Apr 11, 2014 at 13:13
  • @PatrickEvans They're all numbers but they don't repeat. I'm trying to make a basic cipher. – C1D Commented Apr 11, 2014 at 13:15
  • 2 It's worth noting that a "swap" operation like this is problematic for [at least] two reasons: 1) Values are cast to Strings when they become keys so don't be surprised when you have unexpected "[object Object]" keys. And 2) duplicate values (after cast to String) get overwritten. #1, at least, can be solved by producing a Map instead of an Object, thusly: function swap(obj) {return new Map(Object.entries(x).map([k, v] => [v, k]))} – broofa Commented Feb 1, 2019 at 21:44
  • const swap = o => Object.entries(o).reduce((r, [k, v]) => (r[v]=k, r), {}); Similar approach can be used for arrays where values are positive integers/indices. – mpapec Commented Oct 21, 2020 at 8:21
Add a comment  | 

25 Answers 25

Reset to default 189
function swap(json){
  var ret = {};
  for(var key in json){
    ret[json[key]] = key;
  }
  return ret;
}

Example here FIDDLE don't forget to turn on your console to see the results.


ES6 versions:

static objectFlip(obj) {
  const ret = {};
  Object.keys(obj).forEach(key => {
    ret[obj[key]] = key;
  });
  return ret;
}

Or using Array.reduce() & Object.keys()

static objectFlip(obj) {
  return Object.keys(obj).reduce((ret, key) => {
    ret[obj[key]] = key;
    return ret;
  }, {});
}

Or using Array.reduce() & Object.entries()

static objectFlip(obj) {
  return Object.entries(obj).reduce((ret, entry) => {
    const [ key, value ] = entry;
    ret[ value ] = key;
    return ret;
  }, {});
}

Now that we have Object.fromEntries:

const f = obj => Object.fromEntries(Object.entries(obj).map(a => a.reverse()))

console.log(
  f({A : 'a', B : 'b', C : 'c'})
) // => {a : 'A', b : 'B', c : 'C'}

or:

const f = obj => Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]))

console.log(
  f({A : 'a', B : 'b', C : 'c'})
) // => {a : 'A', b : 'B', c : 'C'}

(Updated to remove superfluous parentheses - thanks @devin-g-rhode)

you can use lodash function _.invert it also can use multivlaue

 var object = { 'a': 1, 'b': 2, 'c': 1 };

  _.invert(object);
  // => { '1': 'c', '2': 'b' }

  // with `multiValue`
  _.invert(object, true);
  // => { '1': ['a', 'c'], '2': ['b'] }

Using ES6:

const obj = { a: "aaa", b: "bbb", c: "ccc", d: "ddd" };
Object.assign({}, ...Object.entries(obj).map(([a,b]) => ({ [b]: a })))

Get the keys of the object, and then use the Array's reduce function to go through each key and set the value as the key, and the key as the value.

const data = {
  A: 1,
  B: 2,
  C: 3,
  D: 4
}
const newData = Object.keys(data).reduce(function(obj, key) {
  obj[data[key]] = key;
  return obj;
}, {});
console.log(newData);

In ES6/ES2015 you can combine use of Object.keys and reduce with the new Object.assign function, an arrow function, and a computed property name for a pretty straightforward single statement solution.

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.keys(foo)
    .reduce((obj, key) => Object.assign({}, obj, { [foo[key]]: key }), {});

If you're transpiling using the object spread operator (stage 3 as of writing this) that will simplify things a bit further.

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.keys(foo)
    .reduce((obj, key) => ({ ...obj, [foo[key]]: key }), {});

Finally, if you have Object.entries available (stage 4 as of writing), you can clean up the logic a touch more (IMO).

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.entries(foo)
    .reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {});

2021's answer

The concise way by using ES6 syntax like this.

const obj = {A : 1, B : 2, C : 3, D : 4}

console.log(
  Object.entries(obj).reduce((acc, [key, value]) => (acc[value] = key, acc), {})
);

Explain:

(acc[value] = key, acc)

Using Comma operator (,) syntax.

The comma operator (,) evaluates each of its operands (from left to right) and returns the value of the last operand.

As a complement of @joslarson and @jPO answers:
Without ES6 needed, you can use Object.keys Array.reduce and the Comma Operator:

Object.keys(foo).reduce((obj, key) => (obj[foo[key]] = key, obj), {});

Some may find it ugly, but it's "kinda" quicker as the reduce doesn't spread all the properties of the obj on each loop.

Modern JS solution:

const swapKeyValue = (object) =>
  Object.entries(object).reduce((swapped, [key, value]) => (
    { ...swapped, [value]: key }
  ), {});

Typescript:

type ValidKey = number | string;

const swapKeyValue = <K extends ValidKey, V extends ValidKey>(
  object: Record<K, V>
): Record<V, K> =>
  Object.entries(object)
    .reduce((swapped, [key, value]) => (
      { ...swapped, [value as ValidKey]: key }
    ), {} as Record<V, K>);

Using Ramda:

const swapKeysWithValues = 
  R.pipe(
    R.keys,
    R.reduce((obj, k) => R.assoc(source[k], k, obj), {})
  );

const result = swapKeysWithValues(source);

Try

let swap = (o,r={})=> Object.keys(o).map(k=> r[o[k]]=k) && r;

let obj = {A : 1, B : 2, C : 3, D : 4};

let swap = (o,r={})=> Object.keys(o).map(k=> r[o[k]]=k) && r;

console.log(swap(obj));

With pure Ramda in a pure and point-free style:

const swapKeysAndValues = R.pipe(
   R.toPairs,
   R.map(R.reverse),
   R.fromPairs,
);

Or, with a little more convoluted ES6 version, still pure functional:

const swapKeysAndValues2 = obj => Object
    .entries(obj)
    .reduce((newObj, [key, value]) => ({...newObj, [value]: key}), {})

Shortest one I came up with using ES6..

const original = {
 first: 1,
 second: 2,
 third: 3,
 fourth: 4,
};


const modified = Object
  .entries(original)
  .reduce((all, [key, value]) => ({ ...all, [value]: key }), {});

console.log('modified result:', modified);

    var data = {A : 1, B : 2, C : 3, D : 4}
    var newData = {};
    Object.keys(data).forEach(function(key){newData[data[key]]=key});
    console.log(newData);

Here is a pure functional implementation of flipping keys and values in ES6:

TypeScript

  const flipKeyValues = (originalObj: {[key: string]: string}): {[key: string]: string} => {
    if(typeof originalObj === "object" && originalObj !== null ) {
      return Object
      .entries(originalObj)
      .reduce((
        acc: {[key: string]: string}, 
        [key, value]: [string, string],
      ) => {
        acc[value] = key
        return acc;
      }, {})
    } else {
      return {};
    }
  }

JavaScript

const flipKeyValues = (originalObj) => {
    if(typeof originalObj === "object" && originalObj !== null ) {
        return Object
        .entries(originalObj)
        .reduce((acc, [key, value]) => {
          acc[value] = key
          return acc;
        }, {})
    } else {
        return {};
    }
}

const obj = {foo: 'bar'}
console.log("ORIGINAL: ", obj)
console.log("FLIPPED: ", flipKeyValues(obj))

function swapKV(obj) {
  const entrySet = Object.entries(obj);
  const reversed = entrySet.map(([k, v])=>[v, k]);
  const result = Object.fromEntries(reversed);
  return result;
}

This can make your object, {A : 1, B : 2, C : 3, D : 4}, array-like, so you can have

const o = {A : 1, B : 2, C : 3, D : 4}
const arrayLike = swapKV(o);
arrayLike.length = 5;
const array = Array.from(arrayLike);
array.shift(); // undefined
array; // ["A", "B", "C", "D"]

Here is an option that will swap keys with values but not lose duplicates, if your object is : { a: 1, b: 2, c: 2}, it will always return an array in the output :

function swapMap(map) {
    const invertedMap = {};
    for (const key in map) {
        const value = map[key];
        invertedMap[value] = invertedMap[value] || [];
        invertedMap[value].push(key);
    }
    return invertedMap;
}
swapMap({a: "1", b: "2", c: "2"})
// Returns => {"1": ["a"], "2":["b", "c"]}

A simple TypeScript variant:

const reverseMap = (map: { [key: string]: string }) => {
    return Object.keys(map).reduce((prev, key) => {
        const value = map[key];
        return { ...prev, [value]: [...(prev.value || []), key] };
    }, {} as { [key: string]: [string] })
}

Usage:

const map = { "a":"1", "b":"2", "c":"2" };
const reversedMap = reverseMap(map);
console.log(reversedMap);

Prints: { "1":["a"], "2":["b", "c"] }

Rewriting answer of @Vaidd4, but using Object.assign (instead of comma operator):

/**
 * Swap object keys and values
 * @param {Object<*>} obj
 * @returns {Object<string>}
 */
function swapObject(obj) {
    return Object.keys(obj).reduce((r, key) => (Object.assign(r, {
        [obj[key]]: key,
    })), {});
}

Or, shorter:

Object.keys(obj).reduce((r, key) => (Object.assign(r, {[obj[key]]: key})), {});
function myFunction(obj) {
  return Object.keys(obj).reduce((acc, cur) => {
    return {  ...acc, [obj[cur]]: cur };
     }, {});
}

This is the solution that I'm using:

function objSwap(obj, tl = false) {
    return Object.entries(obj).reduce((a, [k, v]) => (a[v = tl ? v.toLowerCase() : v] = k = tl ? k.toLowerCase() : k, a), {});
}

As a bonus: if you need to swap then check some values I added the possibility to lowercase keys and values. Simply you've to set tl = true, else if you don't need it ...

function objSwap(obj) {
    return Object.entries(obj).reduce((a, [k, v]) => (a[v] = k, a), {});
}

Using a for...of loop:

let obj = {A : 1, B : 2, C : 3, D : 4}

for (let [key, value] of Object.entries(obj)){
    
    obj[value] = key

    delete obj[key]

}

console.log(obj) // {1: 'A', 2: 'B', 3: 'C', 4: 'D'}

ONE OF THE ES6 WAYS IS HERE

const invertObject = (object) =>Object.entries(object).reduce((result, value) =>  ({...result, [value[1]]: value[0] }), {});

let obj = invertObject({A : 1, B : 2, C : 3, D : 4}); 

Here's a type-safe way using TypeScript that has not been suggested before. This solution takes two generics that means the return type will be typed as expected. It's faster than doing methods with .reduce or Object.entries.

// Easier way to type `symbol | number | string` (the only valid keys of an object)
export type AnyKey = keyof any;

export function mirror<K extends AnyKey, V extends AnyKey>(
    object: Record<K, V>,
) {
    const ret: Partial<Record<V, K>> = {};

    for (const key in object) {
        ret[object[key]] = key;
    }

    return ret as Record<V, K>;
}

Usage:

const obj = mirror({
  a: 'b',
  c: 'd',
});

// {b: 'a', d: 'c'}
obj;

I believe it's better to do this task by using an npm module, like invert-kv.

invert-kv: Invert the key/value of an object. Example: {foo: 'bar'} → {bar: 'foo'}

https://www.npmjs.com/package/invert-kv

const invertKv = require('invert-kv');

invertKv({foo: 'bar', unicorn: 'rainbow'});
//=> {bar: 'foo', rainbow: 'unicorn'}

本文标签: javascriptSwap key with value in objectStack Overflow