用对象中的值交换键

我有一个非常大的 JSON 对象,结构如下:

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

我需要一个函数,可以交换的值与键在我的对象,我不知道如何做到这一点。我需要这样的输出:

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

有没有办法我可以做到这一点,将手动创建一个新的对象,其中所有的东西都交换?
谢谢

131356 次浏览
function swap(json){
var ret = {};
for(var key in json){
ret[json[key]] = key;
}
return ret;
}

这里的示例 小提琴不要忘记打开控制台查看结果。


ES6 版本:

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

或者使用 Array reduce ()Key ()

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

或者使用 Array reduce ()Object.entry ()

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

获取对象的键,然后使用 Array 的 reduce 函数遍历每个键并将值设置为键,将键设置为值。

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);

你可以使用 加速度函数它也可以使用多值

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


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


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

在 ES6/ES2015中,您可以将 Object.keys减少的使用与新的 对象. 分配函数、 箭头函数计算属性名结合起来,形成一个非常简单的单语句解决方案。

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

如果您正在使用 物体扩展运算符物体扩展运算符(编写本文时的阶段3)进行传译,那将进一步简化事情。

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

最后,如果有 Object.entry可用(编写时的阶段4) ,则可以稍微清理一下逻辑(IMO)。

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

使用 ES6:

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

使用 拉姆达:

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


const result = swapKeysWithValues(source);

作为@joslarson 和@jPO 的补充答案:
如果不需要 ES6,你可以使用 Object.keysArray.reduce逗号操作符:

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

有些人可能会觉得它难看,但它是“有点”快,因为 reduce不分布的所有属性的 obj在每个循环。

试试看

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));

我认为最好使用 npm 模块(如 invert-kv)来完成这项任务。

反转-kv : 反转对象的键/值。例如: { 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'}

纯粹的拉姆达在一个纯粹的和无点的风格:

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

或者,使用一个稍微复杂一点的 ES6版本,仍然是纯粹的功能:

const swapKeysAndValues2 = obj => Object
.entries(obj)
.reduce((newObj, [key, value]) => ({...newObj, [value]: key}), {})
    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);

现在我们已经有了 Object.from 条目:

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'}

或:

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'}

(更新以删除多余的括号-感谢@devin-g-Rhode)

下面是 ES6中翻转 keysvalues的一个纯功能性实现:

打字机

  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))

最短的一个是我用 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);

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

这可以使您的对象 {A : 1, B : 2, C : 3, D : 4}类似于数组,因此您可以拥有

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"]

这里有一个选项,可以用值交换键,但是不会丢失重复项,如果您的对象是: { a: 1,b: 2,c: 2} ,它将总是在输出中返回一个数组:

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"]}

一个简单的 TypeScript 变体:

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] })
}

用法:

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

印刷品: { "1":["a"], "2":["b", "c"] }

重写@Vaidd4的答案,但使用 Object.assign(而不是 逗号运算符) :

/**
* 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,
})), {});
}

或者,简短一点:

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 };
}, {});
}

2021年的答案

使用 ES6语法的简明方法如下所示。

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


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

解释:

(acc[value] = key, acc)

使用 < strong > 逗号运算符(,) 语法。

The comma operator (,)计算它的每个操作数(< em > 从左到右) 和 返回最后一个操作数的值

这是我正在使用的解决方案:

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), {});
}

作为奖励: 如果你需要交换,然后检查一些值,我增加了小写键和值的可能性。简单地说,你必须设置 tl = true,否则,如果你不需要它..。

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

使用 for...of循环:

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'}

ES6的一条路在这里

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});

下面介绍一种使用 TypeScript 的类型安全方法,这种方法以前从未被建议过。这个解决方案采用两个泛型,这意味着返回类型将按预期类型输入。它比使用 .reduceObject.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>;
}

用法:

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


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

现代 JS 解决方案:

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

打印稿:

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>);