ผสาน 2 อาร์เรย์ของวัตถุ


112

มาดูตัวอย่างกัน

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});

ฉันต้องการผสาน 2 อาร์เรย์ของวัตถุเหล่านั้นและสร้างอาร์เรย์ต่อไปนี้:

arr3 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'});

มีฟังก์ชัน JavaScript หรือ jQuery ที่จะทำสิ่งนี้หรือไม่?

$.extendไม่เหมาะกับฉัน มันกลับมา

arr4 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});

15
เกิดอะไรขึ้นกับ{name: "lang", value: "English"}?
Shadow Wizard is Ear For You

ขออภัย. ฉันพูดถึง $ .extend ไม่ใช่ $ .merge
Alexander

1
ฉันหมายความว่าตรรกะเกี่ยวข้องกับอะไร? คุณต้องการรวมอาร์เรย์อย่างไร? ไม่ชัดเจนจากตัวอย่างของคุณ
Shadow Wizard is Ear For You

ขอบคุณทุกท่านมากครับ. ฉันทำด้วยตนเอง
Alexander

6
@ShadowWizard ฉันคิดว่าสิ่งที่ OP หมายถึงคือการอัปเดตหากมีอยู่และผลักดันหากไม่มี
Amin Mohamed Ajani

คำตอบ:


84

หากคุณต้องการผสาน 2 อาร์เรย์ของวัตถุใน JavaScript คุณสามารถใช้เคล็ดลับบรรทัดเดียวนี้

Array.prototype.push.apply(arr1,arr2);

ตัวอย่างเช่น

var arr1 = [{name: "lang", value: "English"},{name: "age", value: "18"}];
var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

Array.prototype.push.apply(arr1,arr2); 

console.log(arr1);  // final merged result will be in arr1

เอาท์พุต:

[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]

นี่เป็นการใช้งานที่ง่ายที่สุดและใช้งานได้ดี ขอบคุณสำหรับการแบ่งปัน
Leo Caseiro

18
ผลลัพธ์เช่นเดียวกับที่ง่ายกว่ามาก:arr1 = arr1.concat(arr2)
keithpjolley

7
แต่นี่ไม่ใช่การรวม!
Dimitri Kopriwa

1
ผลลัพธ์จะไม่เหมือนกัน concatจะส่งคืนอาร์เรย์ใหม่และทำลายการอ้างอิงที่คุณมี
Bpainter

8
สิ่งนี้ไม่ตอบคำถามอาร์เรย์ผลลัพธ์ควรมี 3 ออบเจ็กต์ไม่ใช่ 4 คุณเปลี่ยนค่าตัวอย่าง โดยพื้นฐานแล้วสิ่งที่ OP ต้องการคือการรวมอาร์เรย์ออบเจ็กต์สองชุดและลบค่าที่ซ้ำกัน
Ranjan

43

ด้วย ES6 คุณสามารถทำได้ง่ายมากดังต่อไปนี้:

var arr1 = new Array({name: "lang", value: "German"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var arr3 = [...arr1, ...arr2];

เอาท์พุต:

    arr3 = [
      {"name":"lang","value":"German"},
      {"name":"age","value":"18"},
      {"name":"childs","value":"5"},
      {"name":"lang","value":"German"}
    ]

6
นี่น่าจะเป็นคำตอบอันดับต้น ๆ
nocdib

20
สิ่งนี้ไม่ได้ทำตามที่ OP กำลังมองหาไม่ควรมีวัตถุชิ้นที่สองประกอบด้วย{ name: 'lang', value: 'German'}
Will

3
ฉันไม่รู้เหตุผลว่าทำไมคำตอบนี้จึงถูกโหวต สิ่งที่ @ daveanderson88 ต้องการแตกต่างจากคำตอบนี้
NguyễnXuânHoàng

33

สำหรับผู้ที่กำลังทดลองสิ่งทันสมัย:

var odd = [
    { name : "1", arr: "in odd" },
    { name : "3", arr: "in odd" }
];

var even = [
    { name : "1", arr: "in even" },
    { name : "2", arr: "in even" },
    { name : "4", arr: "in even" }
];

// ----
// ES5 using Array.filter and Array.find
function merge(a, b, prop){
  var reduced = a.filter(function(aitem){
      return ! b.find(function(bitem){
          return aitem[prop] === bitem[prop];
      });
  });
  return reduced.concat(b);
}
console.log( "ES5", merge(odd, even, "name") );

// ----
// ES6 arrow functions
function merge(a, b, prop){
    var reduced =  a.filter( aitem => ! b.find ( bitem => aitem[prop] === bitem[prop]) )
  return reduced.concat(b);
}
console.log( "ES6", merge(odd, even, "name") );

// ----
// ES6 one-liner
var merge = (a, b, p) => a.filter( aa => ! b.find ( bb => aa[p] === bb[p]) ).concat(b);


console.log( "ES6 one-liner", merge(odd, even, "name") );

// Results
// ( stuff in the "b" array replaces things in the "a" array )
// [
//    {
//         "name": "3",
//         "arr": "in odd"
//     },
//     {
//         "name": "1",
//         "arr": "in even"
//     },
//     {
//         "name": "2",
//         "arr": "in even"
//     },
//     {
//         "name": "4",
//         "arr": "in even"
//     }
// ]

29

อัปเดต 12 ต.ค. 2562

เวอร์ชันใหม่ใช้เฉพาะ Javascript ที่ใหม่กว่าและไม่ต้องใช้ไลบรารีของบุคคลที่สาม

const mergeByProperty = (target, source, prop) => {
  source.forEach(sourceElement => {
    let targetElement = target.find(targetElement => {
      return sourceElement[prop] === targetElement[prop];
    })
    targetElement ? Object.assign(targetElement, sourceElement) : target.push(sourceElement);
  })
}
var target /* arr1 */ = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
var source /* arr2 */ = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

mergeByProperty(target, source, 'name');

console.log(target)

คำตอบนี้เริ่มเก่าไปแล้ว libs เช่น lodash และขีดล่างมีความจำเป็นน้อยลงมากในทุกวันนี้ ในเวอร์ชันใหม่นี้อาร์เรย์เป้าหมาย (arr1)เป็นอาร์เรย์ที่เรากำลังดำเนินการและต้องการอัปเดตอยู่เสมอ แหล่งที่มา (arr2)อาร์เรย์เป็นที่ที่ข้อมูลใหม่ที่มาจากและเราต้องการให้มันรวมเข้าเป็นของเราเป้าหมายอาร์เรย์

เราห่วงมากกว่าแหล่งอาร์เรย์มองหาข้อมูลใหม่และสำหรับวัตถุที่ยังไม่ได้พบในของเราทุกเป้าหมายอาร์เรย์เราก็เพิ่มที่ใช้วัตถุtarget.push (sourceElement) หากอยู่บนพื้นฐานของเราคุณสมบัติที่สำคัญ ( 'ชื่อ')เป็น วัตถุที่มีอยู่แล้วในอาร์เรย์เป้าหมายของเรา - เราปรับปรุงคุณสมบัติและค่าใช้มันObject.assign (targetElement, sourceElement) "เป้าหมาย" ของเราจะเป็นอาร์เรย์เดียวกันและมีเนื้อหาที่อัปเดตเสมอ


คำตอบเก่าใช้ขีดล่างหรือ lodash

ฉันมักจะมาที่นี่จาก Google และฉันมักจะไม่พอใจกับคำตอบ คุณตอบว่าดี แต่จะง่ายกว่าและดีกว่าโดยใช้ underscore.js

สาธิต: http://jsfiddle.net/guya/eAWKR/

นี่คือฟังก์ชันทั่วไปที่จะผสาน 2 อาร์เรย์โดยใช้คุณสมบัติของวัตถุ ในกรณีนี้คุณสมบัติคือ 'ชื่อ'

var arr1 = [{name: "lang", value: "English"}, {name: "age", value: "18"}];
var arr2 = [{name : "childs", value: '5'}, {name: "lang", value: "German"}];

function mergeByProperty(arr1, arr2, prop) {
  _.each(arr2, function(arr2obj) {
    var arr1obj = _.find(arr1, function(arr1obj) {
      return arr1obj[prop] === arr2obj[prop];
    });

    arr1obj ? _.extend(arr1obj, arr2obj) : arr1.push(arr2obj);
  });
}

mergeByProperty(arr1, arr2, 'name');

console.log(arr1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"></script>

[{name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}]

6
เกือบจะเหมือนกันใน LOC ความซับซ้อนเหมือนคำตอบของ @ YOU ยกเว้นว่าจะช้ากว่ามาก (ส่วนใหญ่เกิดจากการเรียกใช้ฟังก์ชันพิเศษและความจริงที่ว่าคำตอบของคุณใช้ประโยชน์จากเคล็ดลับอาร์เรย์ JS Associative เพื่อค้นหารายการที่มีการค้นหา O (1)) นอกจากนี้คุณจำเป็นต้องนำห้องสมุดเพิ่มเติมมาด้วย
Mrchief

คุณจะไม่ได้รับความแตกต่างใด ๆ ในด้านประสิทธิภาพเว้นแต่คุณจะต้องรับมือกับกรณีที่ล้ำหน้า เกี่ยวกับ lib พิเศษ - ขีดล่าง, lodash และเหมือนกันมักใช้กันอยู่แล้วและมีประโยชน์อื่น ๆ เราควรพิจารณาใช้ต่อไป นักพัฒนาและแอปส่วนใหญ่จะได้รับประโยชน์จากความเรียบง่ายและลักษณะทั่วไปของโซลูชันนี้
guya

1
@guya ฉันรู้ว่านี่เป็นเรื่องเก่า แต่โดยทั่วไปแล้วมีการใช้ lodash และเหมือนกันและมีประโยชน์อื่น ๆในขณะที่คุณบอกว่ามันมีประโยชน์อื่น ๆ มันเป็นข้อสันนิษฐานที่ยิ่งใหญ่ที่จะบอกว่าพวกเขามักจะใช้อยู่แล้ว
Craicerjack

26
var arr3 = [];
for(var i in arr1){
   var shared = false;
   for (var j in arr2)
       if (arr2[j].name == arr1[i].name) {
           shared = true;
           break;
       }
   if(!shared) arr3.push(arr1[i])
}
arr3 = arr3.concat(arr2);

ใส่คำอธิบายภาพที่นี่


1
คำตอบนี้มีความซับซ้อนของเวลาที่ไม่ดี (O (n ^ 2)) โซลูชัน O (n) สามารถทำได้โดยใช้แผนที่แฮช
Alex von Brandenfels

19

ง่ายมากโดยใช้ตัวดำเนินการแพร่กระจาย ES6:

const array1 = [{a: 'HI!'}, {b: 'HOW'}]
const array2 = [{c: 'ARE'}, {d: 'YOU?'}]

const mergedArray = [ ...array1, ...array2 ]
console.log('Merged Array: ', mergedArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Merged Array: [ {a: 'HI!'}, {b: 'HOW'} {c: 'ARE'}, {d: 'YOU?'} ]

หมายเหตุ:วิธีแก้ปัญหาข้างต้นคือเพียงแค่ผสานสองอาร์เรย์โดยใช้ตัวดำเนินการกระจาย ES6

แก้ไขเมื่อ 07 มกราคม 2020 โดย @ bh4r4th: เนื่องจากบริบทเปลี่ยนไปเนื่องจากการแก้ไขหลังจากวิธีแก้ไขเบื้องต้นของฉัน ฉันต้องการอัปเดตโซลูชันของฉันให้ตรงกับเกณฑ์ปัจจุบัน กล่าวคือ

  1. รวมวัตถุอาร์เรย์โดยไม่ต้องสร้างวัตถุที่ซ้ำกันและ

  2. อัพเดตvalueว่าnameคุณสมบัตินั้นมีอยู่แล้วในอาร์เรย์ก่อนหน้านี้หรือไม่

const arr1 = [
    { name: "lang", value: "English" },
    { name: "age", value: "18" }
]
const arr2 = [
    { name: "childs", value: '2' }, 
    { name: "lang", value: "German" }
]
const arr3 = [
    { name: "lang", value: "German" },
    { name: "age", value: "28" },
    { name: "childs", value: '5' }
]

// Convert to key value dictionary or object
const convertToKeyValueDict = arrayObj => {
    const val = {}
    arrayObj.forEach(ob => {
        val[ob.name] = ob.value
    })
    return val
}

// update or merge array
const updateOrMerge = (a1, a2) => {
    const ob1 = convertToKeyValueDict(a1)
    const ob2 = convertToKeyValueDict(a2)
    // Note: Spread operator with objects used here
    const merged_obj = {...ob1, ...ob2}
    const val = Object.entries(merged_obj)
    return val.map(obj => ({ name: obj[0], value: obj[1] }))
}

const v1 = updateOrMerge(arr1, arr2)
const v2 = updateOrMerge(v1, arr3)
console.log(`Merged array1 and array2: ${JSON.stringify(v1)} \n\n`)
console.log(`Merged above response and array3: ${JSON.stringify(v2)} \n\n`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับในปี 2019! ฉันจะเสนอวิธีแก้ปัญหาเดียวกันหลังจากดูคำตอบอื่น ๆ ที่มีคะแนนโหวตสูงกว่า! @ อเล็กซานเดอร์พลาดง่าย แต่โปรดยอมรับอันนี้!
iaforek

ไม่ถูกต้อง ผู้ถามต้องการแทนที่ออบเจ็กต์เป็นพิเศษหากมีคุณสมบัติที่ซ้ำกันไม่ใช่แค่ต่อท้าย
HaveSpacesuit

ขอบคุณที่ชี้ว่า @HaveSpacesuit ฉันได้ตอบคำถามนี้ในปี 2018 เมื่อบริบทคือการรวมอาร์เรย์สองอาร์เรย์ จะแก้ไขคำตอบนี้เร็ว ๆ นี้เพื่อใช้setเมื่อผสานเพื่อลบรายการที่ซ้ำกัน สิ่งนี้จะสร้างอาร์กิวเมนต์ตัวแปรใหม่ แต่โค้ดน้อยที่สุด อย่างไรก็ตามฉันไม่ใช่แฟนตัวยงของ payload ที่มีการกำหนดชื่อเป็นคุณสมบัติและค่าเป็นประเภทต่างๆ [ { lang: &#39;German&#39;, age: 25}] แต่ฉันชอบ วิธีนี้น้ำหนักบรรทุกจะลดลงในขณะที่สื่อสารระหว่างบริการ
bh4r4th

ตอนนี้ฉันได้อัปเดตวิธีแก้ปัญหาให้ตรงกับบริบทที่เปลี่ยนแปลงของคำถามแล้ว
bh4r4th

16

การรวมสองอาร์เรย์:

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var result=arr1.concat(arr2);
// result: [{name: "lang", value: "English"}, {name: "age", value: "18"}, {name : "childs", value: '5'}, {name: "lang", value: "German"}]

การผสานสองอาร์เรย์โดยไม่มีค่าที่ซ้ำกันสำหรับ 'name':

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var i,p,obj={},result=[];
for(i=0;i<arr1.length;i++)obj[arr1[i].name]=arr1[i].value;
for(i=0;i<arr2.length;i++)obj[arr2[i].name]=arr2[i].value;
for(p in obj)if(obj.hasOwnProperty(p))result.push({name:p,value:obj[p]});
// result: [{name: "lang", value: "German"}, {name: "age", value: "18"}, {name : "childs", value: '5'}]

Array.concat เป็นวิธีที่เหมาะสมในการรวม 2 อาร์เรย์ให้เป็นหนึ่งเดียว ฉันชอบสมมติฐานเพิ่มเติมว่าแนวคิดของการผสาน "จริง" ได้รับการแก้ไขแล้ว (ตามคีย์ที่กำหนดของแต่ละองค์ประกอบอาร์เรย์)
บ็อบ

14

วิธีที่ง่ายที่สุดคือใช้เวทมนตร์ ES6:

รวมสองรายการที่ซ้ำกัน:

const a = [{a: 1}, {b: 2}]
const b = [{a: 1}]

const result = a.concat(b) // [{a: 1}, {b: 2}, {a: 1}]

หากไม่มีรายการที่ซ้ำกันจะเหมือนกับการบวกด้านบน:

const distinct = [...new Set(result.map(item => item.YOUR_PROP_HERE))]


1
concat ไม่ทำงานกับรายการที่มีลักษณะแตกต่างกัน
fdsfdsfdsfds

7

ด้วย lodash:

_.uniqBy([...arr1, ...arr2], 'name')

ไวยากรณ์ ES6 นั้นใช้ได้กับ 2 อาร์เรย์ไม่ใช่กับ 2 อาร์เรย์ของวัตถุ
Dario

7

นี่คือวิธีที่ฉันแก้ไขปัญหาที่คล้ายกันในบริบท ES6:

function merge(array1, array2, prop) {
    return array2.map(function (item2) {
        var item1 = array1.find(function (item1) {
            return item1[prop] === item2[prop];
        });
        return Object.assign({}, item1, item2);
    });
}

หมายเหตุ: วิธีนี้จะไม่ส่งคืนรายการใด ๆ จาก array1 ที่ไม่ปรากฏใน array2


แก้ไข:ฉันมีบางสถานการณ์ที่ฉันต้องการเก็บรักษารายการที่ไม่ปรากฏในอาร์เรย์ที่สองดังนั้นฉันจึงคิดวิธีอื่นขึ้นมา

function mergeArrays(arrays, prop) {
    const merged = {};

    arrays.forEach(arr => {
        arr.forEach(item => {
            merged[item[prop]] = Object.assign({}, merged[item[prop]], item);
        });
    });

    return Object.values(merged);
}

var arr1 = [
    { name: 'Bob', age: 11 },
    { name: 'Ben', age: 12 },
    { name: 'Bill', age: 13 },
];

var arr2 = [
    { name: 'Bob', age: 22 },
    { name: 'Fred', age: 24 },
    { name: 'Jack', age: 25 },
    { name: 'Ben' },
];

console.log(mergeArrays([arr1, arr2], 'name'));

6

อีกเวอร์ชันหนึ่งโดยใช้reduce() method:

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});

var arr = arr1.concat(arr2).reduce(function(prev, current, index, array){ 
   
   if(!(current.name in prev.keys)) {
      prev.keys[current.name] = index;
      prev.result.push(current);   
   } 
   else{
       prev.result[prev.keys[current.name]] = current;
   }  

   return prev;
},{result: [], keys: {}}).result;
  
document.getElementById("output").innerHTML = JSON.stringify(arr,null,2);    
<pre id="output"/>


สิ่งนี้ได้ผลดีสำหรับฉัน ปัญหาเล็ก ๆ อย่างหนึ่งคือบางครั้งการสั่งซื้อก็แปลกเมื่อรวมวัตถุ json ขนาดใหญ่ 3 ชิ้น
crh225


4

คุณสามารถใช้วัตถุเพื่อรวบรวมคุณสมบัติของคุณในขณะที่แทนที่รายการที่ซ้ำกันแล้วขยาย / แบนวัตถุนั้นกลับไปที่อาร์เรย์ สิ่งนี้:

function merge(args) {
    args  = Array.prototype.slice.call(arguments);
    var o = { };
    for(var i = 0; i < args.length; ++i)
        for(var j = 0; j < args[i].length; ++j)
            o[args[i][j].name] = args[i][j].value;
    return o;
}

function expand(o) {
    var a = [ ];
    for(var p in o)
        if(o.hasOwnProperty(p))
            a.push({ name: p, value: o[p]});
    return a;
}

var arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
var arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
var arr3 = expand(merge(arr1, arr2));

ฉันไม่รู้ว่านี่เป็นวิธีที่เร็วที่สุดหรือไม่ แต่ใช้ได้กับอาร์เรย์อินพุตจำนวนเท่าใดก็ได้ ตัวอย่างเช่นสิ่งนี้:

var a = expand(
    merge(
        [{name: "lang", value: "English"}, {name: "age", value: "18"}],
        [{name: "childs", value: '5'}, {name: "lang", value: "German"}],
        [{name: 'lang', value: 'Pancakes'}]
    )
);

ให้สิ่งเดียวกันกับคำaว่าarr3"เยอรมัน" แทนที่ด้วย "แพนเค้ก"

แนวทางนี้ถือว่าวัตถุของคุณมี{name: ..., value: ...}รูปแบบเดียวกันทั้งหมด

คุณสามารถดูได้ที่นี่ (โปรดเปิดคอนโซลของคุณ): http://jsfiddle.net/ambiguous/UtBbB/


2

แล้ว jQuery Merge ล่ะ?

http://api.jquery.com/jQuery.merge/

ตัวอย่าง jsFiddle ที่นี่: http://jsfiddle.net/ygByD/


ซึ่งจะไม่แทนที่ภาษาอังกฤษเป็นภาษาเยอรมันตามที่ระบุการผสานจะเกิดขึ้นพร้อมnameคุณสมบัติ
สั้นเกินไป

ใช่คุณพูดถูก! ฉันไม่เห็นสเปคนั้นคร่าวๆ!
321X

+1. ดี! ในทางกลับกันมันเป็นฟังก์ชั่นที่ดีในการผสานอาร์เรย์ของวัตถุจาวาสคริปต์
มูฮัมหมัดราฮีล

2

ฉันประสบปัญหาเดียวกันและจากคำตอบของ guyaฉันได้ขยายไลบรารีขีดล่างและเพิ่มฟังก์ชันการทำงานอีกเล็กน้อยที่ฉันต้องการ นี่คือสรุปสาระสำคัญ

/**
 * Merges two object-like arrays based on a key property and also merges its array-like attributes specified in objectPropertiesToMerge.
 * It also removes falsy values after merging object properties.
 *
 * @param firstArray The original object-like array.
 * @param secondArray An object-like array to add to the firstArray.
 * @param keyProperty The object property that will be used to check if objects from different arrays are the same or not.
 * @param objectPropertiesToMerge The list of object properties that you want to merge. It all must be arrays.
 * @returns The updated original array.
 */
function merge(firstArray, secondArray, keyProperty, objectPropertiesToMerge) {

    function mergeObjectProperties(object, otherObject, objectPropertiesToMerge) {
        _.each(objectPropertiesToMerge, function (eachProperty) {
            object[eachProperty] = _.chain(object[eachProperty]).union(otherObject[eachProperty]).compact().value();
        });
    }

    if (firstArray.length === 0) {
        _.each(secondArray, function (each) {
            firstArray.push(each);
        });
    } else {
        _.each(secondArray, function (itemFromSecond) {
            var itemFromFirst = _.find(firstArray, function (item) {
                return item[keyProperty] === itemFromSecond[keyProperty];
            });

            if (itemFromFirst) {
                mergeObjectProperties(itemFromFirst, itemFromSecond, objectPropertiesToMerge);
            } else {
                firstArray.push(itemFromSecond);
            }
    });
    }

    return firstArray;
}

_.mixin({
            merge: merge
        });

หวังว่าจะเป็นประโยชน์! ความนับถือ!


2

ฉันเพิ่งนิ่งงันกับปัญหานี้และฉันมาที่นี่ด้วยความหวังว่าจะได้คำตอบ แต่คำตอบที่ยอมรับนั้นใช้ 2 สำหรับในลูปซึ่งฉันไม่ชอบ ในที่สุดฉันก็จัดการทำด้วยตัวเอง ไม่ได้ขึ้นอยู่กับไลบรารีใด ๆ :

function find(objArr, keyToFind){
    var foundPos = objArr.map(function(ob){
        return ob.type;
    }).indexOf(keyToFind);
    return foundPos;
}

function update(arr1,arr2){
    for(var i = 0, len = arr2.length, current; i< len; i++){
        var pos = find(arr1, arr2[i].name); 
        current = arr2[i];
        if(pos !== -1) for(var key in arr2) arr1[pos][key] = arr2[key];
        else arr1[arr1.length] = current;
    } 
}

นอกจากนี้ยังรักษาลำดับของ arr1


2

คุณสามารถใช้ฟังก์ชันต่อไปนี้

const merge = (a, b, key = "id") =>
  a.filter(elem => !b.find(subElem => subElem[key] === elem[key]))
   .concat(b);

และลอง

merge(arr1, arr2, 'name');

ขอบคุณวิธี Diago ที่มีคุณสมบัติไม่เปลี่ยนรูป ES6 `` ส่งออก const mergeArrays = (a1, a2, key = "id") => a1 && a2! = null? [... a1.filter (a =>! a2.find (p => p [คีย์] === a [คีย์])), ... a2]: null; ``
มูซา

1

ที่นี่ฉันกรองarr1ตามองค์ประกอบที่มีอยู่ก่อนarr2หรือไม่ หากมีอยู่อย่าเพิ่มลงในอาร์เรย์ผลลัพธ์มิฉะนั้นให้เพิ่ม จากนั้นฉันก็ต่อท้ายarr2ผลลัพธ์

arr1.filter(item => {
  if (!arr2.some(item1=>item.name==item1.name)) {
    return item
  }
}).concat(arr2)

กรุณาให้คำอธิบายสำหรับคำตอบของคุณ ดังนั้นหากคนอื่นอ่านคำถามและคำตอบก็จะเข้าใจได้ง่าย
Mittal Patel

แม้ว่าคำตอบนี้อาจจะถูกต้องและมีประโยชน์ แต่ก็เป็นที่ต้องการหากคุณใส่คำอธิบายไว้ด้วยเพื่ออธิบายว่าจะช่วยแก้ปัญหาได้อย่างไร สิ่งนี้จะมีประโยชน์อย่างยิ่งในอนาคตหากมีการเปลี่ยนแปลง (อาจไม่เกี่ยวข้อง) ที่ทำให้หยุดทำงานและผู้ใช้ต้องเข้าใจว่าครั้งหนึ่งเคยทำงานอย่างไร
Erty Seidohl

ขอบคุณทุกคน. ฉันอัปเดตคำอธิบายโซลูชัน ถ้าเห็นว่าถูกต้องกรุณา
โหวต

0

ปิดด้านบนของหัวของฉัน - ลองขยาย jquery

var arr3 = jQuery.extend(arr1,arr2....)

ขออภัย. ฟังก์ชันนี้จะคืนค่า arr4 ไม่ใช่ $ .merge อันสุดท้ายก็ไม่เหมาะกับฉันเช่นกันเพราะมันซ้ำซ้อนกับวัตถุ
Alexander

0

var newArray = yourArray.concat(otherArray); console.log('Concatenated newArray: ', newArray);


ฉันยอมรับว่าสิ่งนี้สมเหตุสมผลมากกว่าArray.protype.push.apply()คำตอบ แต่มันไม่ได้ทำการผสานอย่างที่ OP ต้องการ
keithpjolley

คุณไม่สามารถรับเอาต์พุตด้านบนโดยใช้ 'concat' ได้หากคุณมีอาร์เรย์ของออบเจ็กต์ผสานสองชุด โปรดตรวจสอบjsfiddle.net/jahanzaibaslam/z22n5tuo
Jahanzaib Aslam

0

ขึ้นอยู่กับคำตอบของ @ YOU แต่รักษาลำดับ:

var arr3 = [];
for(var i in arr1){
   var shared = false;
   for (var j in arr2)
       if (arr2[j].name == arr1[i].name) {
           arr3.push(arr1[j]
           shared = true;
           break;
       }
   if(!shared) arr3.push(arr1[i])
}

for(var j in arr2){
   var shared = false;
   for (var i in arr1)
       if (arr2[j].name == arr1[i].name) {
           shared = true;
           break;
       }
   if(!shared) arr3.push(arr2[j])
}
arr3

ฉันรู้ว่าโซลูชันนี้มีประสิทธิภาพน้อยกว่า แต่จำเป็นหากคุณต้องการรักษาคำสั่งซื้อและยังคงอัปเดตออบเจ็กต์


0

นี่คือปลั๊กอิน jQuery ที่ฉันเขียนเพื่อรวมอาร์เรย์วัตถุสองชุดเข้าด้วยกัน โปรดทราบว่าสิ่งนี้จะปรับเปลี่ยนอาร์เรย์ปลายทางในตำแหน่ง

(function($) {
  $.extendObjectArray = function(destArray, srcArray, key) {
    for (var index = 0; index < srcArray.length; index++) {
      var srcObject = srcArray[index];
      var existObject = destArray.filter(function(destObj) {
        return destObj[key] === srcObject[key];
      });
      if (existObject.length > 0) {
        var existingIndex = destArray.indexOf(existObject[0]);
        $.extend(true, destArray[existingIndex], srcObject);
      } else {
        destArray.push(srcObject);
      }
    }
    return destArray;
  };
})(jQuery);

var arr1 = [
  { name: "lang",   value: "English" },
  { name: "age",    value: "18"      }
];
var arr2 = [
  { name: "childs", value: '5'       },
  { name: "lang",   value: "German"  }
];
var arr3 = $.extendObjectArray(arr1, arr2, 'name');

console.log(JSON.stringify(arr3, null, 2));
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


เวอร์ชัน ES6

(function($) {
  $.extendObjectArray = (destArr, srcArr, key) => {
    srcArr.forEach(srcObj => (existObj => {
      if (existObj.length) {
        $.extend(true, destArr[destArr.indexOf(existObj[0])], srcObj);
      } else {
        destArr.push(srcObj);
      }
    })(destArr.filter(v => v[key] === srcObj[key])));
    return destArr;
  };
})(jQuery);

0

ใช้ lodash ที่คุณต้องการ _.uniqBy

var arr3 = _.uniqBy(arr1.concat(arr2), 'name'); // es5

let arr3 = _.uniqBy([...arr1, ...arr2], 'name'); // es6

คำสั่งของ arr1, arr2 เรื่อง!

ดูเอกสารhttps://lodash.com/docs/4.17.4#uniqBy


จำเป็นต้องใช้บุคคลที่สาม?
NguyễnXuânHoàng

ไม่ แต่เป็นวิธีที่กระชับที่สุดในการบรรลุเป้าหมายและไม่ใช่แค่บุคคลที่สามเท่านั้น
danday74

0
const extend = function*(ls,xs){
   yield* ls;
   yield* xs;
}

console.log( [...extend([1,2,3],[4,5,6])]  );

2
อย่าให้คำตอบของคำถาม อธิบายด้วยว่าวิธีนี้แก้ปัญหาอย่างไร
Mittal Patel

0
merge(a, b, key) {
    let merged = [];
    a.forEach(aitem => {
        let found = b.find( bitem => aitem[key] === bitem[key]);
        merged.push(found? found: aitem);
    });
    return merged;
}

0

หากคุณต้องการผสาน 2 อาร์เรย์ แต่ลบวัตถุที่ซ้ำกันให้ใช้สิ่งนี้ มีการระบุรายการที่ซ้ำกัน.uniqueIdของแต่ละออบเจ็กต์

function mergeObjectArraysRemovingDuplicates(firstObjectArray, secondObjectArray) {
  return firstObjectArray.concat(
    secondObjectArray.filter((object) => !firstObjectArray.map((x) => x.uniqueId).includes(object.uniqueId)),
  );
}

0

ลองสิ่งนี้:

var a = [{"a":20, "b":10,"c":"c","d":"asd","f":"any"}]
var b = [{"a":20, "b":10,"c":"c", "e":"nan","g":10200}]

var p = []
_.map(a, function(da){
var chk = _.filter(b, function(ds){
return da.a ===ds.a
})[0]
p.push(_.extend(da, chk))


})

console.log(p)

OutPut จะเป็น:

  [{
    "a": 20,
    "b": 10,
    "c": "c",
    "d": "asd",
    "f": "any",
    "e": "nan",
    "g": 10200
  }]

0
const arr1 = ["Vijendra","Singh"];
const arr2 = ["Singh", "Shakya"];

arr2.forEach(item => {
        if(!arr1.find(k => k===item))
          arr1.push(item)
    });


console.log(arr1)

0

โซลูชันที่ใช้ JS Map:

const merge = (arr1, arr2, prop) => {
    const resultMap = new Map([...arr1.map((item) => [item[prop], item])]);
    arr2.forEach((item) => {
        const mapItem = resultMap.get(item[prop]);
        if (mapItem) Object.assign(mapItem, item);
        else resultMap.set(item[prop], item);
    });
    return [...resultMap.values()];
};

const arr1 = new Array({name: "lang", value: "English"}, {name: "age", value: "18"});
const arr2 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});

console.log(merge(arr1, arr2, "name"));

ซึ่งผลิต:

ผลลัพธ์ของฟังก์ชันผสาน ()


0
const array1 = [{id:1,name:'ganza'},
{id:2,name:'respice dddd'},{id:4,name:'respice dddd'},{id:6,name:'respice dddd'},
{id:7,name:'respice dddd'}];
const array2 = [{id:1,name:'ganza respice'},{id:2,name:'respice'},{id:3,name:'mg'}];

 function mergeTwoArray(array1,array2){

    return array1.map((item,i)=>{
        if(array2[i] && item.id===array2[i].id){
          return array2[i];
          }else{
            return item;
          }
    });
  }

const result = merge(array1,array2);
console.log(result);
//here is the result:  Array [Object { id: 1, name: "ganza respice" }, Object { id: 2, name: "respice" }, Object { id: 4, name: "respice dddd" }, Object { id: 6, name: "respice dddd" }, Object { id: 7, name: "respice dddd" }]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.