The answer from Muhammad imran is effective if the purpose/target is a simple inversion (i.e. no nested object structure; no multiple values).
Obviously that is the best result to be achieved, if no further artifice is created, to cover the fact that the key->value relation in objects are:
- keys are unique,
- values can be muliple.
Looking at the beer example above it is somewhat regretible that the information is lost in the inversion. Therefore this answer should supplement and enrich and provide a way in which the information can be stored. The way to achieve it is using Javascript Arrays within the resulting inverted object, to allow to store the potentially ambigious new values. as for example.
var BeerAtoB = {
"amore" : "love",
"alimenti": "food",
"Bier" : "beer",
"cerveza" : "beer",
"pivo" : "beer",
"birra" : "beer",
"cerveja" : "beer"
};
allowing to translate (de,es,pl/cz,it,pt)"beer" to English would best store
this information in the inverted too
var BeerBtoA = {
"love" : "amore",
"food" : "alimenti",
"beer" : [ "Bier" ,
"cerveza",
"pivo",
"birra",
"cerveja"
]
};
a version in which less information get lost and the multipleness of the original value "beer" is reflected by multipleness of values under the joint, inverted key "beer" now.
To accomplish this I made an enhanced inverting function
function invertObject(obj)
{
var invertedObject = {};
// make a stack and prime it with the obj
var stack = [];
stack.push({"way":[],"obj":obj});
// while stuff on the stack
while (stack.length)
{
var way= stack[0].way;
var obj= stack[0].obj;
for (var prop in obj)
{
if (typeof obj[prop] === 'object')
{
// attributes, which are themselves objects are added to the stack,
// with their way information.
stack.push({"way":way.concat(prop),"obj":obj[prop]});
}
else
{
// always start with adding things to the invertedObject,
var curobj = invertedObject;
var value = newKey = obj[prop];
var curpath = way.concat(prop).concat(obj[prop]);
// for all but the last two path elements the loop below
// will create the inverted path, starting with the value (obj[prop])
// as key, Since values need not be unique (as keys), create each
// such new key-property as an Array, not to loose inverted pathes.
while(curpath.length>2)
{
var pathpart = curpath.pop();
if(!curobj.hasOwnProperty(pathpart))
{
curobj[pathpart]=[];
}
curobj=curobj[pathpart];
}
// the last two curpath Array members represent the last key and the
// new to be added value.
var preLastPart = curpath.pop();
var lastPart = curpath.pop();
// Again the artifice of an Array is used since
// the inverted keys are not unique, hence cases in which
// 1 key has (>1) values.
if(!curobj.hasOwnProperty(preLastPart))
{
curobj[preLastPart]=[];
}
curobj[preLastPart].push(lastPart);
}
}
stack.shift();
}
return invertedObject; function invertObject(obj)
{
var invertedObject = {};
// make a stack and prime it with the obj
var stack = [];
stack.push({"way":[],"obj":obj});
// while stuff on the stack
while (stack.length)
{
var way= stack[0].way;
var obj= stack[0].obj;
for (var prop in obj)
{
if (typeof obj[prop] === 'object')
{
// attributes, which are themselves objects are added to the stack,
// with their way information.
stack.push({"way":way.concat(prop),"obj":obj[prop]});
}
else
{
// always start with adding things to the invertedObject,
var curobj = invertedObject;
var value = newKey = obj[prop];
var curpath = way.concat(prop).concat(obj[prop]);
// for all but the last two path elements the loop below
// will create the inverted path, starting with the value (obj[prop])
// as key, Since values need not be unique (as keys), create each
// such new key-property as an Array, not to loose inverted pathes.
while(curpath.length>2)
{
var pathpart = curpath.pop();
if(!curobj.hasOwnProperty(pathpart))
{
curobj[pathpart]=[];
}
curobj=curobj[pathpart];
}
// the last two curpath Array members represent the last key and the
// new to be added value.
var preLastPart = curpath.pop();
var lastPart = curpath.pop();
// Again the artifice of an Array is used since
// the inverted keys are not unique, hence cases in which
// 1 key has (>1) values.
if(!curobj.hasOwnProperty(preLastPart))
{
curobj[preLastPart]=[];
}
curobj[preLastPart].push(lastPart);
}
}
stack.shift();
}
return invertedObject;
}
}
Indeed since equal values can be found in many places of simple and nested object, the result will be an object in which each value will be an Array for two reasons:
Several original object's keys, can have the same value, and therefore (after inverting) more than one value can exists. An Array can store all those multiple new values, hence all information.
While in an nested object, the uniqueness makes every property either a direct value or a subobject, in the inverted object at a key, we can find not only muliple values, but also that at the very same place there are also further nested objects. (For this reason it is lucky that an Javascript Array, as being an Object, does besides its entry allow also for further properties to be attached to it and hence can serve simultaneously as a storage for the multiple values and as a subkey in the nested structure. Such a double purpose of Arrays in the inverted object structure, is unforunatelly hard to show in JSON notation, as the JSON notation does not allow for Arrays with Object Attributes)
foroverObject.keys( AtoB )would suffice.var makeStuffInverted = { "food":"agriculture", "beer": {"hops":{...},"water":{...},"malt":{...}}}according to the idea that the former values are the new keys. subkeys remain subkeys. but primary keys get mapped to new values and former values to primary (i.e. first level) keys