我已调整/更正了示例对象,因为它们之前包含错误。
我有一个如下所示的映射对象:
var AtoB = {
"amore" : "love",
"alimenti": "food",
"Bier" : "beer"
};
允许映射一种方式,即AtoB["love"]
产生"amore"
。我可以手工添加一个反面,即。
var BtoA = {
"love": "amore",
"food": "alimenti",
"beer": "Bier"
};
无论如何,两个对象同步会很麻烦,我想在Javascript中以编程方式创建BtoA。是否有某种function xyz()
产生var BtoA = xyz(AtoB);
?
上面的示例可以扩展为包含问题(例如,如果我有太多"beer"
)
var AtoB = {
"amore" : "love",
"alimenti": "food",
"Bier" : "beer"
"cerveza" : "beer",
"pivo" : "beer",
"birra" : "beer",
"cerveja" : "beer"
};
因为这不是一对一的映射。在amateuer数学术语中它不是一个不可逆的函数?
为了让事情变得更复杂,我有一个灾难的秘诀。
var makeStuff = {
"agriculture": "food",
"hops" : {
"water": {
"malt": "beer"},
"malt": {
"water": "beer"}},
"water" : {
"hops": {
"malt": "beer"},
"malt": {
"hops": "beer"}},
"malt" : {
"water": {
"hops": "beer"},
"hops": {
"water": "beer"}}
};
反转这个嵌套的 javascript对象,似乎对这样的xyz()
函数更加挑剔。无论如何也许有这样一个xyz()
函数,那么我很乐意接受这个作为这个问题的答案
答案 0 :(得分:1)
很简单。以下是反向键值的代码。
var inverse= (function inv(param){
for(var attr in param) {
if(param.hasOwnProperty(attr)) {
if(typeof param[attr]==="string") {
param[param[attr]] = attr;
delete param[attr];
} else if (Object.prototype.toString.call(param[attr]) === "[object Object]") {
param[attr] = inv(param[attr]);
}
}
}
return param;
});
要将结果输入其他对象,请将其初始化为空并分配。像
var BtoA = {};
BtoA = inverse(AtoB);
而且,JSON:
var AtoB = {
"love": "amore",
"food": "alimenti",
"beer": "Bier",
"beer": "cerveza",
"beer": "pivo",
"beer": "birra",
"beer": "cerveja",
};
只有三个属性,因为JSON是字典数据结构:新密钥将替换旧密钥。所以上面的JSON实际上就像:
{love: "amore", food: "alimenti", beer: "cerveja"}
因此,反转上面给出的JSON(AtoB)将导致只有三个属性的反转,最终结果将是:
{amore: "love", alimenti: "food", cerveja: "beer"}
答案 1 :(得分:0)
如果目的/目标是简单的反转(即没有嵌套的对象结构;没有多个值),则answer from Muhammad imran有效。
显然,这是最好的结果,如果没有创建进一步的技巧,则涵盖对象中的key->值关系是这样的事实:
观察上面的啤酒示例,在倒置中信息丢失有些令人难以置信。因此,这个答案应该补充和丰富,并提供一种可以存储信息的方式。实现它的方法是在生成的反转对象中使用Javascript Arrays,以允许存储潜在的ambigious新值。例如。
var BeerAtoB = {
"amore" : "love",
"alimenti": "food",
"Bier" : "beer",
"cerveza" : "beer",
"pivo" : "beer",
"birra" : "beer",
"cerveja" : "beer"
};
允许翻译(de,es,pl / cz,it,pt)"啤酒"英语最好的存储 这个信息在倒置中也是
var BeerBtoA = {
"love" : "amore",
"food" : "alimenti",
"beer" : [ "Bier" ,
"cerveza",
"pivo",
"birra",
"cerveja"
]
};
一个版本,其中较少的信息丢失和原始价值的多重性"啤酒"联合,倒置的关键"啤酒"现在
为了实现这一点,我做了一个增强的反转功能
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;
}
}
实际上,由于可以在简单和嵌套对象的许多位置找到相等的值,因此结果将是一个对象,其中每个值都是一个数组,原因有两个:
多个原始对象的键可以具有相同的值,因此(反转后)可以存在多个原始值。 Array可以存储所有这些多个新值,因此可以存储所有信息。
在嵌套对象中,唯一性使得每个属性都是直接值或子对象,在键的倒置对象中,我们不仅可以找到多个值,还可以找到那里的多个值也是进一步嵌套的对象。 (由于这个原因,幸运的是Javascript数组,作为一个Object,除了它的条目之外还允许附加属性,因此可以同时作为多个值的存储和嵌套中的子键结构。在倒置的对象结构中,这种数组的双重目的,在JSON表示法中难以显示,因为JSON notation does not allow for Arrays with Object Attributes)