Javascript 将两个嵌套对象组合在一起,同时保留这两个对象的特性,同时将重复的关键帧和值添加在一起
我看过几篇关于将两个对象合并在一起的文章,但大多数都是用于合并包含不包含嵌套元素的对象的对象。当我实现其中一个建议的解决方案时,一个对象的属性被覆盖Javascript 将两个嵌套对象组合在一起,同时保留这两个对象的特性,同时将重复的关键帧和值添加在一起,javascript,Javascript,我看过几篇关于将两个对象合并在一起的文章,但大多数都是用于合并包含不包含嵌套元素的对象的对象。当我实现其中一个建议的解决方案时,一个对象的属性被覆盖 const Gnome = () => { return { ExpRate: .20, Abilities: { PickDoors: 1, }, Buffs: { NightSight: 65, MagicRes: 5, }, ... Additi
const Gnome = () => {
return {
ExpRate: .20,
Abilities: {
PickDoors: 1,
},
Buffs: {
NightSight: 65,
MagicRes: 5,
},
... Additional data and behaviors
};
}
const Thief = () {
return {
ExpRate: 2.10,
Abilities: {
Thievery: 1,
PickDoors: 1,
},
Buffs: {},
// ... Additional data and behavors
};
}
我一直在尝试将这两个对象合并为:
{
ExpRate: 2.30,
Abilities: {
PickDoors: 2,
Thievery: 1
},
Buffs: {
NightSight: 65,
MagicRes: 5,
},
// ... Additional data and behavors from both objects
};
但是,使用Object.assign将覆盖现有键中的值,从而丢失数据。即:
const myGnome = Gnome();
const myThief = Thief();
const myPlayer = Object.assign({}, myGnome, myThief);
我尝试了一些人们推荐的合并方法,但它们似乎都具有与Object.assign()相同的行为;
如有任何建议,将不胜感激。如果这确实是一篇重复的文章,我很喜欢它的链接
提前感谢。您可以使用递归来实现。下面是一个例子
constgnome=()=>{
返回({
表达式:.20,
能力:{
扒门:1,
},
浅黄色:{
夜视:65,
麦基克雷斯:5,
}
});
}
警察小偷=()=>{
返回({
出口率:2.10,
能力:{
盗窃:1,,
扒门:1,
},
buff:{}
});
}
让小偷=小偷();
让gnone=Gnome();
函数合并(obj1、obj2){
设keys1=对象。键(obj1);
设keys2=Object.keys(obj2);
让objToReturn=Object.assign({},obj1,obj2);
让sameKeys=[…新集合(keys1.filter(key=>keys2.includes(key)).concat(keys2.filter(key=>keys1.includes(key)))]
sameKeys.forEach(key=>{
如果(obj1[key]=“object”的类型)objToReturn[key]=合并(obj1[key],obj2[key]);
否则OBJTORETRUN[钥匙]=obj2[钥匙]+obj1[钥匙];
})
返回objToReturn;
}
日志(合并(小偷,gnone))代码>您可以迭代条目并检查是否找到对象,然后再次调用嵌套对象的函数。如果找到数字,则添加此值
函数合并(a、b){
函数mergeTo(源、目标){
Object.entries(source.forEach([k,v])=>{
if(数组isArray(v)){
目标[k]=目标[k]| |[];
目标[k]。推送(…v);
返回;
}
if(v&&typeof v=='object'){
mergeTo(v,target[k]=target[k]|{});
返回;
}
if(typeof v=='number'){
目标[k]=(目标[k]| 0)+v;
返回;
}
如果(!(目标中的k)){
目标[k]=v;
返回;
}
目标[k]=Array.isArray(目标[k])
?[…目标[k],v]
:[目标[k],v];
});
}
var对象={};
合并到(a,对象);
合并到(b,对象);
返回对象;
}
console.log(合并(
{ExpRate:.20,异能:{PickDoors:1},增益:{NightSight:65,MagicRes:5},数组:[1,2],v:'a'},
{ExpRate:2.10,异能:{thiever:1,PickDoors:1},增益:{},数组:[3,4],v'b',f:true}
));代码>
.as控制台包装{最大高度:100%!重要;顶部:0;}
感谢您的回复。我会试试你的建议。我能够按照建议编写一个函数:
function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item));
}
function mergeDeep(target, source) {
let output = Object.assign({}, target);
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach(key => {
if (isObject(source[key])) {
if (!(key in target))
Object.assign(output, { [key]: source[key] });
else
output[key] = mergeDeep(target[key], source[key]);
} else {
if(typeof target[key] === 'number' && typeof source[key] === 'number'){
source[key] += target[key];
}
Object.assign(output, { [key]: source[key] });
}
});
}
return output;
}
console.log(
mergeDeep(
{ExpRate: .20, Abilities: {PickDoors: 1}, Buffs: {NightSight: 65, MagicRes: 5}},
{ExpRate: 2.10, Abilities: {Thievery: 1, PickDoors: 1}}
));
我将尝试其他建议,因为我担心上述方法可能会变得有点复杂,并在将来导致问题。我认为您应该自己编写一个递归函数来处理此任务。@Timothy McCune如果ExpRate
是字符串,会发生什么?如果值为string
或Boolean
实际上什么都没有,将被过滤掉。也许应该在数组中收集该值。但我认为op应该回答这个问题。这种方法非常有效!甚至在添加每个对象的行为时(即:向两个对象添加pickDoors()方法)。这个想法是要有几个种族有特定的能力和增益和专业能力。某些种族/职业组合可能具有相同的技能。如果种族/职业组合包含相同的技能定义,则将它们添加到数组中,以避免对象中的重复函数。谢谢。谢谢你的来信。在我为每个对象介绍一些行为之前,这非常有效。IE:向小偷添加一个偷偷的方法很好,但是如果我向两个对象都添加一个PickDoor方法,那么合并将不会产生期望的结果。