数组编程面试题:补全合并对象数组的JavaScript代码
合并两个数组中同名对象的属性(JavaScript实现)
嘿,我来帮你搞定这个对象合并的需求!咱们先理清楚:有两个数组,drunk_ppl存着饮酒者的基本信息,smoker存着吸烟者的吸烟习惯,要把名字相同的对象所有属性合并到一起,最终放到drunkard数组里对吧?
原始代码片段
你给出的初始代码是这样的:
drunk_ppl = [ {name: 'Mark', age: 20, alcohol_type: 'Whiskey'}, {name: 'Jon', age: 25, alcohol_type: 'Rum'}, {name: 'April', age: 22, alcohol_type: 'Gin'}, {name: 'Simon', age: 50, alcohol_type: 'Vodka'} ]; smoker = [ {name: 'Mark', cig_a_day: 20, brand: 'Marlboro'}, {name: 'Jon', cig_a_day: 15, brand: 'Camel'}, {name: 'April', cig_a_day: 12, brand: 'Newport'}, {name: 'Simon', cig_a_day: 5, brand: 'Dunhill'} ]; var drunkard = []; //创建空数组 for(var i = 0; i < drunk_ppl.length; i++...
补全后的基础实现(嵌套循环)
先给你补全最直观的嵌套循环写法,容易理解:
drunk_ppl = [ {name: 'Mark', age: 20, alcohol_type: 'Whiskey'}, {name: 'Jon', age: 25, alcohol_type: 'Rum'}, {name: 'April', age: 22, alcohol_type: 'Gin'}, {name: 'Simon', age: 50, alcohol_type: 'Vodka'} ]; smoker = [ {name: 'Mark', cig_a_day: 20, brand: 'Marlboro'}, {name: 'Jon', cig_a_day: 15, brand: 'Camel'}, {name: 'April', cig_a_day: 12, brand: 'Newport'}, {name: 'Simon', cig_a_day: 5, brand: 'Dunhill'} ]; var drunkard = []; //创建空数组 for(var i = 0; i < drunk_ppl.length; i++) { // 先拿当前的饮酒者对象 const currentDrunk = drunk_ppl[i]; // 遍历吸烟者数组找同名的 for(var j = 0; j < smoker.length; j++) { const currentSmoker = smoker[j]; if(currentDrunk.name === currentSmoker.name) { // 用展开运算符合并两个对象的所有属性 const mergedObj = {...currentDrunk, ...currentSmoker}; // 也可以用Object.assign:const mergedObj = Object.assign({}, currentDrunk, currentSmoker); drunkard.push(mergedObj); // 找到匹配的就跳出内层循环,别白跑啦 break; } } } // 打印看看结果 console.log(drunkard);
更高效的优化写法
如果数组里的元素特别多,嵌套循环效率就有点低了。咱们可以先把smoker转成一个以名字为键的映射表,这样找同名对象就不用一遍遍遍历了:
drunk_ppl = [ {name: 'Mark', age: 20, alcohol_type: 'Whiskey'}, {name: 'Jon', age: 25, alcohol_type: 'Rum'}, {name: 'April', age: 22, alcohol_type: 'Gin'}, {name: 'Simon', age: 50, alcohol_type: 'Vodka'} ]; smoker = [ {name: 'Mark', cig_a_day: 20, brand: 'Marlboro'}, {name: 'Jon', cig_a_day: 15, brand: 'Camel'}, {name: 'April', cig_a_day: 12, brand: 'Newport'}, {name: 'Simon', cig_a_day: 5, brand: 'Dunhill'} ]; var drunkard = []; // 用reduce把smoker转成{名字: 吸烟者对象}的映射 const smokerMap = smoker.reduce((map, item) => { map[item.name] = item; return map; }, {}); // 遍历饮酒者数组,直接通过名字取对应的吸烟信息合并 drunk_ppl.forEach(drunk => { const smokerInfo = smokerMap[drunk.name]; if(smokerInfo) { drunkard.push({...drunk, ...smokerInfo}); } }); console.log(drunkard);
小提示
- 合并对象时,如果两个对象有同名属性(比如这里两个数组的对象都有
name),后面的对象属性会覆盖前面的。不过在这个场景下name值是一样的,所以完全没问题。 - 优化写法的时间复杂度是O(n),比嵌套循环的O(n*m)快很多,数据量大的时候优势明显。
内容的提问来源于stack exchange,提问作者Akash Goel
相关产品推荐
相关产品推荐

