2012-11-10 28 views
5

Po przeszukiwaniu interwebza przez kilka godzin nie znalazłem rozwiązania, którego szukam.Unia Array obiektów w JavaScript?

Mam dwie tablice zawierające obiekty gier z dużą ilością informacji w środku. (np. tytuł, ślimak, miniatura, podsumowanie, gatunek, data wydania ...).

Array 1 jest zbiorem obiektów pasujących do zainteresowań użytkownika podane podczas rejestracji.

Array 2 jest zbiorem obiektów, które pasują do zakupionych gier podobnych użytkowników. (Podobne użytkownicy są te, które mają wspólne interesy)

Problem: To jest możliwe, a co dzieje się w moim przypadku, istnieją dwa identyczne gry - gra w tablicy 1 jest również w tablicy 2. W pierwszym tablica jest tam, ponieważ pasuje do zainteresowań użytkownika. W drugiej szacie gra jest dostępna, ponieważ podobny użytkownik kupił tę grę.

Pytanie: underscore.js ma miłą funkcji Unii() http://underscorejs.org/#union który daje związek dwóch tablic, ale to nie działa z tablicą obiektów, tylko na wartościach pierwotnych. Jak mogłem sprawić, by działało, dając mi połączenie szeregu obiektów?

+0

Więc co trzeba jest głęboko seryjnej i rozszerzenia? https://gist.github.com/1868955 http://stackoverflow.com/questions/7549574/merge-js-objects-without-overwriting http://stackoverflow.com/questions/896043/how-can-i- merge-2-javascript-objects-populating-the-properties-in-one-if-one-d – jcolebrand

+0

http://phrogz.net/JS/ArraySetMath.js – Phrogz

+1

Wiem, że to nie jest twoje pytanie, ale czy ty rozważane przy użyciu unikalnych gier i używania obiektu klucz: wartość dla swoich kolekcji? – cbayram

Odpowiedz

14

Można bardzo łatwo wdrożyć własne. W takim przypadku funkcja ta jest generyczna, dzięki czemu może pobierać tablice dowolnego typu danych i łączyć je za pomocą dostarczonej funkcji komparatora.

// arr1 and arr2 are arrays of any length; equalityFunc is a function which 
// can compare two items and return true if they're equal and false otherwise 
function arrayUnion(arr1, arr2, equalityFunc) { 
    var union = arr1.concat(arr2); 

    for (var i = 0; i < union.length; i++) { 
     for (var j = i+1; j < union.length; j++) { 
      if (equalityFunc(union[i], union[j])) { 
       union.splice(j, 1); 
       j--; 
      } 
     } 
    } 

    return union; 
} 

function areGamesEqual(g1, g2) { 
    return g1.title === g2.title; 
} 

// Function call example 
arrayUnion(arr1, arr2, areGamesEqual); 

Patrz Object comparison in JavaScript różnych implementacjach porównawczych przedmiot.

+0

Pokonaj mnie. Niezła realizacja. – L0j1k

+0

Hmm nie ma szczęścia, żeby to zadziałało. Zwraca niezdefiniowane. https://gist.github.com/4049901 –

+0

Tak, to nie jest zaskakujące, gdy zapomniałem "zwrócić" wartość. :) Edycja. –

1

jQuery ma metodę extend:

$.extend(true, object1, object2); 
+0

Podobnie jest z underscore.js, ale szukałem operacji związkowej. Rozciągnij się od tego, co rozumiem, do łączenia dwóch obiektów. Chcę całkowicie wyeliminować obiekt, jeśli jest już w tablicy. Myślę, że możesz użyć funkcji extend(), to nie była pierwsza rzecz, która przyszła mi do głowy. –

2

Korzystanie podkreślenia przedłużyć, można zrobić:

var objects = [{ bar : 1, nuts : 2} , {foo : 3, nuts : 4}] 
_.extend.apply(this,objects) 

Jeśli lista może być pusta, należy dołączyć pusty obiekt do niego.

4

Można to zrobić za pomocą podkreślenia sposób:

// collectionUnion(*arrays, iteratee) 
function collectionUnion() { 
    var args = Array.prototype.slice.call(arguments); 
    var it = args.pop(); 

    return _.uniq(_.flatten(args, true), it); 
} 

to tylko doskonalenie pierwotnej funkcji _.union(*arrays), dodając iteratee pracować Collection (tablicę obiektu).

Oto jak go używać:

var result = collectionUnion(a, b, c, function (item) { 
    return item.id; 
}); 

Oryginalny funkcja, która jest po prostu pracować z tablicy, wygląda na to, że:

_.union = function() { 
    return _.uniq(flatten(arguments, true, true)); 
}; 

A premia pełny przykład:

// collectionUnion(*arrays, iteratee) 
function collectionUnion() { 
    var args = Array.prototype.slice.call(arguments); 
    var it = args.pop(); 

    return _.uniq(_.flatten(args, true), it); 
} 

var a = [{id: 0}, {id: 1}, {id: 2}]; 
var b = [{id: 2}, {id: 3}]; 
var c = [{id: 0}, {id: 1}, {id: 2}]; 

var result = collectionUnion(a, b, c, function (item) { 
    return item.id; 
}); 

console.log(result); // [ { id: 0 }, { id: 1 }, { id: 2 }, { id: 3 } ] 
+0

W zbiorze unii (ostatni bonus pełny przykład) użyję: '_.uniqBy (_. Flatten (args, true), 'prop-id')' https://lodash.com/docs/4.17.4 #uniqBy – Crisboot

1

Set (ES6/ES2015) pomoże.

const info1 = {id: 1} 
 
const info2 = {id: 2} 
 
const info3 = {id: 3} 
 

 
const array1 = [info1, info2] 
 
const array2 = [info1, info3] 
 

 
const union = [...new Set([...array1, ...array2])] 
 

 
console.log(union)