我想要反转对象的映射(可能有重复的值)。例如:
const city2country = {
'Amsterdam': 'Netherlands',
'Rotterdam': 'Netherlands',
'Paris': 'France'
};
reverseMapping(city2country)
应输出:
{
'Netherlands': ['Amsterdam', 'Rotterdam'],
'France': ['Paris']
}
我想出了以下天真的解决方案:
const reverseMapping = (obj) => {
const reversed = {};
Object.keys(obj).forEach((key) => {
reversed[obj[key]] = reversed[obj[key]] || [];
reversed[obj[key]].push(key);
});
return reversed;
};
但我很确定有一个更整洁,更短的方式,最好是原型,所以我可以这样做:
const country2cities = city2country.reverse();
感谢。
答案 0 :(得分:6)
您可以使用Object.assign
,同时尊重插入值的给定数组。
const city2country = { Amsterdam: 'Netherlands', Rotterdam: 'Netherlands', Paris: 'France' };
const reverseMapping = o => Object.keys(o).reduce((r, k) =>
Object.assign(r, { [o[k]]: (r[o[k]] || []).concat(k) }), {})
console.log(reverseMapping(city2country));

答案 1 :(得分:2)
JavaScript中没有这样的内置函数。您的代码看起来很好,但鉴于此处有太多边缘情况可能出错,我建议使用invertBy
from lodash,它完全按照您的描述进行操作。
var object = { 'a': 1, 'b': 2, 'c': 1 }; _.invertBy(object); // => { '1': ['a', 'c'], '2': ['b'] }
答案 2 :(得分:0)
你可以使用这样的东西来抢先重复:
function removeDuplicates(arr, key) {
if (!(arr instanceof Array) || key && typeof key !== 'string') {
return false;
}
if (key && typeof key === 'string') {
return arr.filter((obj, index, arr) => {
return arr.map(mapObj => mapObj[key]).indexOf(obj[key]) === index;
});
} else {
return arr.filter(function(item, index, arr) {
return arr.indexOf(item) == index;
});
}
}
然后用它来反转:
function reverseMapping(obj){
var ret = {};
for(var key in obj){
ret[obj[key]] = key;
}
return ret;
}
答案 3 :(得分:0)
您可以使用reduce来保存声明行reduce。
在使用&&
之前,滥用map[object[key]]
检查是否先定义Array.concat
。
它更短,但更简单吗?可能不是,但有点乐趣;)
const reverseMapping = (object) =>
Object.keys(object).reduce((map, key) => {
map[object[key]] = map[object[key]] && map[object[key]].concat(key) || [key]
return map;
}, {});
答案 4 :(得分:0)
您可以尝试从当前对象获取值数组和键数组,并设置一个新对象来保存结果。然后,循环遍历值数组 -
Netherlands
,则创建一个新数组,获取已存在的值(例如:Rotterdam
),并添加此值和新值( Amsterdam
)到数组,并将此数组设置为Netherlands
键的新值。France
是关键字,Paris
是值。代码 -
const city2country = {
'Amsterdam': 'Netherlands',
'Rotterdam': 'Netherlands',
'Paris': 'France',
};
function reverseMapping(obj) {
let values = Object.values(obj);
let keys = Object.keys(obj);
let result = {}
values.forEach((value, index) => {
if(!result.hasOwnProperty(value)) {
// create new entry
result[value] = keys[index];
}
else {
// duplicate property, create array
let temp = [];
// get first value
temp.push(result[value]);
// add second value
temp.push(keys[index]);
// set value
result[value] = temp;
}
});
console.log(result);
return result;
}
reverseMapping(city2country)

这里的好处是 - 它会根据当前对象的结构进行调整 - Netherlands
是重复值,在新对象中获取数组作为值,而France
得到字符串值Paris
作为其属性。当然,改变它应该很容易。
注意 - 旧浏览器可能不支持Object.values()。
答案 5 :(得分:0)
@Nina Scholz 的回答非常适合这个确切的问题。 :thumbsup:
但是如果您不需要保留荷兰键 ("Netherlands": ["Amsterdam", "Rotterdam"]
) 的两个值,那么这段代码会更短更易于阅读:
const city2country = { Amsterdam: 'Netherlands', Rotterdam: 'Netherlands', Paris: 'France' };
console.log(
Object.entries(city2country).reduce((obj, item) => (obj[item[1]] = item[0]) && obj, {})
);
// outputs `{Netherlands: "Rotterdam", France: "Paris"}`