Scal 2 tablice obiektów

112

Spójrzmy na przykład.

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

Muszę scalić te 2 tablice obiektów i utworzyć następującą tablicę:

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

Czy jest do tego funkcja JavaScript lub jQuery?

$.extendmi nie pasuje. Wraca

arr4 = new Array({name : "childs", value: '5'}, {name: "lang", value: "German"});
Alexander
źródło
15
Co się stało {name: "lang", value: "English"}?
Shadow Wizard is Ear For You
Przepraszam. Mam na myśli $ .extend, a nie $ .merge.
Alexander
1
To znaczy, jaka jest logika? Jak chcesz scalić tablice? Z twoich przykładów nie wynika jasno.
Shadow Wizard is Ear For You
Bardzo wam wszystkim dziękuję. Zrobiłem to ręcznie.
Alexander
6
@ShadowWizard, myślę, że to, co oznaczało OP, to aktualizacja, jeśli istnieje, i push, jeśli nie.
Amin Mohamed Ajani

Odpowiedzi:

84

Jeśli chcesz połączyć 2 tablice obiektów w JavaScript. Możesz użyć tej jednej sztuczki

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

Na przykład

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

Wynik:

[{"name":"lang","value":"English"},
{"name":"age","value":"18"},
{"name":"childs","value":"5"},
{"name":"lang","value":"German"}]
Jahanzaib Aslam
źródło
Jak dotąd jest to najprostsze użycie i działa dobrze. Dzięki za udostępnienie.
Leo Caseiro
17
taki sam wynik jak znacznie prostszy:arr1 = arr1.concat(arr2)
keithpjolley
7
ale to nie jest scalanie!
Dimitri Kopriwa
1
Wyniki nie są takie same. concatzwróci nową tablicę i zepsuje wszelkie posiadane odniesienia.
Bpainter
8
To nie odpowiada na pytanie, wynikowa tablica powinna mieć 3 obiekty, a nie 4. Zmieniłeś przykładowe wartości. Zasadniczo OP chce scalić dwie tablice obiektów i usunąć zduplikowane wartości.
Ranjan
43

Dzięki ES6 możesz to zrobić bardzo łatwo, jak poniżej:

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];

Wynik:

    arr3 = [
      {"name":"lang","value":"German"},
      {"name":"age","value":"18"},
      {"name":"childs","value":"5"},
      {"name":"lang","value":"German"}
    ]
Nguyễn Bá Vinh
źródło
6
To powinna być najlepsza odpowiedź.
nocdib
20
To nie robi tego, czego szukał OP, nie powinno być drugiego obiektu zawierającego{ name: 'lang', value: 'German'}
Will
3
Nie wiem, dlaczego ta odpowiedź jest głosowana. To, czego chce @ daveanderson88, to inna odpowiedź.
Nguyễn Xuân Hoàng
33

Dla tych, którzy eksperymentują z nowoczesnymi rzeczami:

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"
//     }
// ]
pion
źródło
29

Zaktualizuj 12 października 2019 r

Nowa wersja oparta wyłącznie na nowszym Javascript i bez konieczności korzystania z biblioteki zewnętrznej.

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)

Ta odpowiedź się starzeje, biblioteki takie jak lodash i underscore są obecnie znacznie mniej potrzebne. W nowej wersji tablica docelowa (arr1) jest tą, z którą pracujemy i którą chcemy być na bieżąco. Tablica źródłowa (arr2) to miejsce, z którego pochodzą nowe dane i chcemy, aby zostały scalone z naszą tablicą docelową .

Mamy pętla nad źródłowego tablicy poszukuje nowych danych, a dla każdego obiektu, który nie jest jeszcze w naszym docelowym tablicy po prostu dodać, że obiekt przy target.push (sourceElement) Jeżeli na podstawie naszego mienia kluczowego ( „nazwa”) , obiekt jest już w naszej tablicy docelowej - aktualizujemy jego właściwości i wartości za pomocą Object. assign (targetElement, sourceElement) . Naszym „celem” będzie zawsze ta sama tablica i zaktualizowana zawartość.


Stara odpowiedź za pomocą podkreślenia lub lodash

Zawsze przyjeżdżam tutaj z Google i zawsze nie jestem zadowolony z odpowiedzi. TWOJA odpowiedź jest dobra, ale będzie łatwiej i schludniej, używając podkreślenia.js.

DEMO: http://jsfiddle.net/guya/eAWKR/

Oto bardziej ogólna funkcja, która połączy 2 tablice przy użyciu właściwości ich obiektów. W tym przypadku właściwością jest „nazwa”

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'}]
guya
źródło
6
Prawie identyczne w LOC, złożoność jak odpowiedź @ YOU, z tym wyjątkiem, że jest to znacznie wolniejsze (głównie z powodu dodatkowych wywołań funkcji i faktu, że odpowiedź YOU wykorzystuje sztuczkę tablic asocjacyjnych JS do znajdowania elementów za pomocą wyszukiwania O (1)). To poza tym, że musisz zabrać ze sobą dodatkową bibliotekę.
Mrchief
Nie uzyskasz żadnej różnicy w wydajności, chyba że masz do czynienia z skrajnymi przypadkami. Jeśli chodzi o dodatkową bibliotekę - podkreślenia, lodash i podobne są na ogół już używane i mają inne zalety, i tak należy rozważyć ich użycie. Większość programistów i aplikacji skorzysta na prostocie i ogólności tego rozwiązania.
guya
1
@guya Zdaję sobie sprawę, że to jest stare, ale podkreślenie, lodash i podobne są na ogół już używane i mają inne zalety, podczas gdy, jak mówisz, mają inne zalety, jest to ogromne założenie, że są już ogólnie używane.
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);

wprowadź opis obrazu tutaj

TY
źródło
1
Ta odpowiedź ma złą złożoność czasową (O (n ^ 2)). Rozwiązanie O (n) jest możliwe przy użyciu mapy skrótów.
Alex von Brandenfels
19

Bardzo proste przy użyciu operatora rozproszenia 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?'} ]

Uwaga: powyższe rozwiązanie polega na scaleniu dwóch tablic za pomocą operatora rozproszenia ES6.

Edytuj w dniu 07 stycznia 2020 r. Przez @ bh4r4th: Ponieważ kontekst zmienił się z powodu zmian po moim początkowym rozwiązaniu. Chciałbym zaktualizować moje rozwiązanie, aby spełniało obecne kryteria. to znaczy,

  1. Scalaj obiekty w szyku bez tworzenia zduplikowanych obiektów i

  2. zaktualizuj, valuejeśli namewłaściwość już istnieje w poprzedniej tablicy

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>

bh4r4th
źródło
1
To powinna być akceptowana odpowiedź w 2019 roku! Zamierzałem zaproponować to samo rozwiązanie, patrząc na inne odpowiedzi z wyższą liczbą głosów! @Alexander Łatwo go przegapić, ale zaakceptuj to!
iaforek
Błędny. Osoba pytająca w szczególności chce ZMIENIĆ obiekty, jeśli mają one zduplikowaną właściwość, a nie po prostu je dołączyć.
HaveSpacesuit
Dzięki za wskazanie tego @HaveSpacesuit. Odpowiedziałem na to pytanie w 2018 roku, kiedy kontekst ma po prostu scalić dwie tablice. Wkrótce zmodyfikuje tę odpowiedź, aby użyć jej setpo scaleniu do usunięcia duplikatów. Stworzyłoby to nowy argument zmiennej, ale minimalny kod. Jednak nie jestem wielkim fanem ładunku, który ma nazwy zdefiniowane jako właściwości i wartości jako różne typy. Zamiast tego wolę [ { lang: &#39;German&#39;, age: 25}] . W ten sposób waga ładunku zostanie zminimalizowana podczas komunikacji między usługami.
bh4r4
Zaktualizowałem rozwiązanie, aby pasowało do zmienionego kontekstu pytania.
bh4r4
16

Łączenie dwóch tablic:

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"}]

Scalanie dwóch tablic bez zduplikowanych wartości dla „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'}]
Andrew D.
źródło
Array.concat to właściwy sposób na połączenie 2 tablic w jedną. Podoba mi się również rozszerzone założenie, że zaadresowano pojęcie „prawdziwego” scalania (na podstawie danego klucza każdego elementu tablicy).
bob
14

Najłatwiej jest z magią ES6:

Połącz dwa z duplikatami:

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

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

Bez duplikatów to to samo co powyżej plus:

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

knikolov
źródło
1
concat nie działa z elementami o różnej naturze
fdsfdsfdsfds
7

Z lodash:

_.uniqBy([...arr1, ...arr2], 'name')
Pietro
źródło
że składnia ES6 działa z 2 tablicami, a nie z 2 tablicami obiektów.
Dario,
7

Oto jak rozwiązałem podobny problem w kontekście 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);
    });
}

Uwaga: to podejście nie zwróci żadnych elementów z tablicy1, które nie pojawiają się w tablicy2.


EDYCJA: Mam kilka scenariuszy, w których chcę zachować elementy, które nie pojawiają się w drugiej tablicy, więc wymyśliłem inną metodę.

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'));
marktuk
źródło
6

Jeszcze inna wersja wykorzystująca 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"/>

Vadim Gremyachev
źródło
To działało świetnie dla mnie. Jednym małym problemem jest jednak to, że kolejność czasami jest dziwna podczas łączenia 3 dużych obiektów
JSON
5

Proste rozwiązanie

var tx = [{"id":1},{"id":2}];
var tx1 = [{"id":3},{"id":4}];


var txHistory = tx.concat(tx1)

console.log(txHistory); 
// output
 // [{"id":1},{"id":2},{"id":3},{"id":4}];
Shashwat Gupta
źródło
4

Możesz użyć obiektu, aby zebrać swoje właściwości, zastępując duplikaty, a następnie rozwinąć / spłaszczyć ten obiekt z powrotem do tablicy. Coś takiego:

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));

Nie wiem, czy to najszybszy sposób, ale działa dla dowolnej liczby tablic wejściowych; na przykład to:

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

Daje to samo, co w przypadku a, arr3gdy „niemiecki” został zastąpiony przez „naleśniki”.

To podejście zakłada, że ​​wszystkie twoje obiekty mają {name: ..., value: ...}oczywiście tę samą formę.

Możesz zobaczyć, jak działa tutaj (otwórz swoją konsolę): http://jsfiddle.net/ambiguous/UtBbB/

mu jest za krótkie
źródło
2

A co z jQuery Merge?

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

Przykład jsFiddle tutaj: http://jsfiddle.net/ygByD/

321X
źródło
To nie zastąpi angielskiego z niemieckim, jak określono, scalanie odbywa się wzdłuż namewłaściwości.
mu jest za krótkie
AH tak, masz rację! Nie widziałem tej specyfikacji od razu!
321X
+1. Dobrze! z drugiej strony całkiem niezłą funkcją jest scalanie tablic obiektów javascript
Muhammad Raheel
2

Miałem ten sam problem i na podstawie odpowiedzi guya rozszerzyłem bibliotekę podkreśleń, a także dodałem nieco więcej funkcji, których potrzebowałem. Oto streszczenie .

/**
 * 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
        });

Mam nadzieję, że okaże się przydatny! Pozdrowienia!

Nahuel Barrios
źródło
2

Niedawno byłem zaskoczony tym problemem i przyszedłem tutaj z nadzieją na odpowiedź, ale zaakceptowana odpowiedź wykorzystuje 2 w pętlach, których nie wolałbym. W końcu udało mi się stworzyć własny. Nie zależy od żadnej biblioteki:

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;
    } 
}

Utrzymuje to również kolejność arr1.

Amin Mohamed Ajani
źródło
2

Możesz użyć następującej funkcji

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

i próbuj

merge(arr1, arr2, 'name');
Diogo Alves
źródło
Dzięki Diago Way z niezmienną funkcją ES6 `` export const mergeArrays = (a1, a2, key = "id") => a1 && a2! = Null? [... a1.filter (a =>! a2.find (p => p [klucz] === a [klucz])), ... a2]: null; ``
Musa
1

Tutaj najpierw filtruję arr1na podstawie elementu obecnego arr2lub nie. Jeśli jest obecny, nie dodawaj go do wynikowej tablicy, w przeciwnym razie dodaj. A następnie dołączam arr2do wyniku.

arr1.filter(item => {
  if (!arr2.some(item1=>item.name==item1.name)) {
    return item
  }
}).concat(arr2)
maulik bhatt
źródło
Prosimy o wyjaśnienie swojej odpowiedzi. Więc jeśli jakakolwiek inna osoba przeczyta pytanie i odpowie, będzie łatwo to zrozumieć.
Mittal Patel
Chociaż ta odpowiedź jest prawdopodobnie poprawna i przydatna, najlepiej jest dołączyć do niej jakieś wyjaśnienie, aby wyjaśnić, w jaki sposób pomaga ona rozwiązać problem. Staje się to szczególnie przydatne w przyszłości, jeśli nastąpi zmiana (prawdopodobnie niezwiązana), która spowoduje, że przestanie działać, a użytkownicy muszą zrozumieć, jak kiedyś działało.
Erty Seidohl,
Dzięki chłopaki. Zaktualizowałem opis rozwiązania. Jeśli wydaje się to poprawne, proszę zagłosuj za :)
maulik bhatt
0

Z góry mojej głowy - spróbuj rozszerzyć jQuery

var arr3 = jQuery.extend(arr1,arr2....)
Xhalent
źródło
Przepraszam. Dokładnie ta funkcja zwraca arr4. Nie $ .merge. Ten ostatni też mi nie odpowiada, ponieważ powiela obiekty.
Alexander
0

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

javaScriptBeard
źródło
Zgadzam się, że ma to o wiele więcej sensu niż Array.protype.push.apply()odpowiedź, ale nie działa tak, jak chciał OP.
keithpjolley
nie możesz uzyskać powyższego wyniku używając 'concat', jeśli masz dwie tablice scalające obiektów. Sprawdź to jsfiddle.net/jahanzaibaslam/z22n5tuo
Jahanzaib Aslam
0

Na podstawie odpowiedzi @ YOU, ale zachowując kolejność:

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

Wiem, że to rozwiązanie jest mniej wydajne, ale jest konieczne, jeśli chcesz zachować porządek i nadal aktualizować obiekty.

hcarreras
źródło
0

Oto wtyczka jQuery, którą napisałem, aby scalić dwie tablice obiektów za pomocą klucza. Należy pamiętać, że powoduje to lokalną modyfikację tablicy docelowej.

(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>


Wersja 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);
Panie Polywhirl
źródło
0

Używając lodash chcesz _.uniqBy

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

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

Kolejność arr1, arr2 ma znaczenie!

Zobacz dokumenty https://lodash.com/docs/4.17.4#uniqBy

danday74
źródło
potrzebujesz użyć strony trzeciej?
Nguyễn Xuân Hoàng
nie, ale jest to najbardziej zwięzły sposób osiągnięcia tego, i nie jest to byle jaka osoba trzecia, jego lodash!
danday74
0
const extend = function*(ls,xs){
   yield* ls;
   yield* xs;
}

console.log( [...extend([1,2,3],[4,5,6])]  );
codemonkey
źródło
2
Po prostu nie udzielaj odpowiedzi na pytanie. Wyjaśnij również, jak to rozwiązanie rozwiązuje problem.
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;
}
Kyaw
źródło
0

Jeśli chcesz scalić 2 tablice, ale usunąć zduplikowane obiekty, użyj tego. Duplikaty są identyfikowane na .uniqueIdkażdym obiekcie

function mergeObjectArraysRemovingDuplicates(firstObjectArray, secondObjectArray) {
  return firstObjectArray.concat(
    secondObjectArray.filter((object) => !firstObjectArray.map((x) => x.uniqueId).includes(object.uniqueId)),
  );
}
daveanderson88
źródło
0

Spróbuj tego:

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 będzie:

  [{
    "a": 20,
    "b": 10,
    "c": "c",
    "d": "asd",
    "f": "any",
    "e": "nan",
    "g": 10200
  }]
Rohit Parte
źródło
0
const arr1 = ["Vijendra","Singh"];
const arr2 = ["Singh", "Shakya"];

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


console.log(arr1)
Gajju
źródło
0

Rozwiązanie wykorzystujące mapę JS:

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"));

Który produkuje:

merge () wynik funkcji

2DH
źródło
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" }]
Ganza respice
źródło