Javascript - map value for keys (displaying the inverse object)

I want to change the display of an object (which may have duplicate values). Example:

const city2country = { 'Amsterdam': 'Netherlands', 'Rotterdam': 'Netherlands', 'Paris': 'France' }; 

reverseMapping(city2country) Should output:

 { 'Netherlands': ['Amsterdam', 'Rotterdam'], 'France': ['Paris'] } 

I came up with the following naive solution:

 const reverseMapping = (obj) => { const reversed = {}; Object.keys(obj).forEach((key) => { reversed[obj[key]] = reversed[obj[key]] || []; reversed[obj[key]].push(key); }); return reversed; }; 

But I'm sure there is a neater, shorter path, preferably prototyped, so I could just do:

 const country2cities = city2country.reverse(); 

Thanks.

+5
source share
5 answers

You can use Object.assign by observing this array of inserted values.

 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)); 
+5
source

JavaScript has no such built-in function. Your code looks great, but given that there are so many cross cases here that it might be wrong, I suggest using invertBy from lodash , which does exactly what you are describing.

Example

 var object = { 'a': 1, 'b': 2, 'c': 1 }; _.invertBy(object); // => { '1': ['a', 'c'], '2': ['b'] } 
+2
source

You can use something like this to attack duplicates first:

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

and then use this to make it inverse:

 function reverseMapping(obj){ var ret = {}; for(var key in obj){ ret[obj[key]] = key; } return ret; } 
0
source

You can use abbreviation to save the reduce declaration line.

Violating && to check if map[object[key]] Array.concat before using Array.concat .

It's shorter, but is it easier? Probably not, but a bit of fun;)

 const reverseMapping = (object) => Object.keys(object).reduce((map, key) => { map[object[key]] = map[object[key]] && map[object[key]].concat(key) || [key] return map; }, {}); 
0
source

You can try to get an array of values ​​and an array of keys from the current object and configure a new object to store the result. Then when you iterate over an array of values ​​-

  • If the object already has this value as a key, for example Netherlands , you create a new array, extract the existing value (ex: Rotterdam ) and add this and the new value ( Amsterdam ) to the array and configure this array as the new value for the Netherlands key.
  • If the current value does not exist in the object, set it as a new line, ex: France is the key, and Paris is the value.

Code -

 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) 

The advantage here is that it adjusts the structure of your current object - the Netherlands , which is duplicate values, gets the array as the value in the new object, while France gets the string value Paris because it is a property. Of course, this should be very easy to change.

Note. Object.values ​​() may not be supported in older browsers.

0
source

Source: https://habr.com/ru/post/1270952/


All Articles