2015-12-21 35 views
15

Mam dwa literały obiektowe tak:Najlepszy sposób na przecięcie się kluczy dwóch obiektów?

var firstObject = 
{ 
    x: 0, 
    y: 1, 
    z: 2, 

    a: 10, 
    b: 20, 
    e: 30 
} 

var secondObject = 
{ 
    x: 0, 
    y: 1, 
    z: 2, 

    a: 10, 
    c: 20, 
    d: 30 
} 

Chcę dostać się do skrzyżowania z klawiszy te dwa literały obiektowe mają tak:

var intersectionKeys = ['x', 'y', 'z', 'a'] 

oczywiście mogę zrobić pętlę i sprawdzić, czy klucz o tej samej nazwie istnieje w drugim obiekcie, ale zastanawiam się, czy byłby to dobry przypadek dla jakiegoś programowania funkcjonalnego i mapy/filtra/zmniejszenia użycia? Ja sam nie zrobiłem tak wiele programowania funkcjonalnego, ale mam wrażenie, że może istnieć czyste i sprytne rozwiązanie tego problemu.

+1

Lodash ma przecięcie [] (https://lodash.com/docs#intersection) jako metoda, jeśli nie byli już świadomi . – Xotic750

+0

@ Xotic750 Wydaje się działać tylko z tablicami? Z drugiej strony, prawdopodobnie istnieje wiele sposobów jak "Object.keys", aby uzyskać klucze jako tablicę. – Piwwoli

+3

Oczywiście potrzebne będą klucze każdego obiektu, podobnie jak w poniższych odpowiedziach, ["Object.keys"] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ Global_Objects/Object/keys) lub lodash ma ['_.keys'] (https://lodash.com/docs#keys). '_.intersection (_. keys (firstObject), _.keys (secondObject));' – Xotic750

Odpowiedz

19

rozwiązanie bez indexOf.

var firstObject = { x: 0, y: 1, z: 2, a: 10, b: 20, e: 30 }, 
 
    secondObject = { x: 0, y: 1, z: 2, a: 10, c: 20, d: 30 }; 
 

 
function intersection(o1, o2) { 
 
    return Object.keys(o1).concat(Object.keys(o2)).sort().reduce(function (r, a, i, aa) { 
 
     if (i && aa[i - 1] === a) { 
 
      r.push(a); 
 
     } 
 
     return r; 
 
    }, []); 
 
} 
 

 
document.write('<pre>' + JSON.stringify(intersection(firstObject, secondObject), 0, 4) + '</pre>');

drugiej próby z O (n).

var firstObject = { x: 0, y: 1, z: 2, a: 10, b: 20, e: 30 }, 
 
    secondObject = { x: 0, y: 1, z: 2, a: 10, c: 20, d: 30 }; 
 

 
function intersection(o1, o2) { 
 
    return Object.keys(o1).filter({}.hasOwnProperty.bind(o2)); 
 
} 
 

 
document.write('<pre>' + JSON.stringify(intersection(firstObject, secondObject), 0, 4) + '</pre>');

+0

Mam wrażenie, obiekty js są zawsze sortowane według klucza ... –

+1

@AmitKriplani nie gwarantowane w ogóle w ES5 i gwarantowane, że są w porządku tworzenia w ES2015 – zerkms

+2

@NinaScholz: to miła odpowiedź. Byłoby jeszcze ładniej, gdyby 'reduce' był czysty (nie korzystał z darmowego' wyniku') PS: OP nie dba o równość wartości - to tylko przecięcie nazw kluczowych – zerkms

4

Procedura będę sugerować to:

  1. Pobierz array kluczy przy użyciu Object.keys() dla jednego z obiektów.
  2. Znajdź przecięcie tablicy używając .filter i sprawdź, czy drugi obiekt zawiera klucz pasujący do pierwszej tablicy.

var firstObject = { 
 
    x: 0, 
 
    y: 1, 
 
    z: 2, 
 

 
    a: 10, 
 
    b: 20, 
 
    e: 30 
 
} 
 

 
var secondObject = { 
 
    x: 0, 
 
    y: 1, 
 
    z: 2, 
 

 
    a: 10, 
 
    c: 20, 
 
    d: 30 
 
} 
 

 
function getIntKeys(obj1, obj2){ 
 

 
    var k1 = Object.keys(obj1); 
 
    return k1.filter(function(x){ 
 
     return obj2[x] !== undefined; 
 
    }); 
 
    
 
} 
 

 
alert(getIntKeys(firstObject, secondObject));

+0

Prawdopodobnie zastanawiałem się nad tym samym, jak to ma znaczenie, czy robisz 'k1.filter' lub' k2.filter' w każdym przypadku ? – Piwwoli

+0

@HunanRostomyan Nie sądzę, że kiedykolwiek może być fałszywa, ponieważ pierwsza wartość w funkcji oddzwaniania filtru zwraca bieżącą wartość odfiltrowanej macierzy.W tym przypadku k1 jest filtrowany, co sprawia, że ​​pierwsza kontrola jest zbędna, ponieważ wiemy, że wartość musi istnieć, gdy jest przekazywana przez wywołanie zwrotne. –

+1

@Piwwoli Nie ma znaczenia, przecięcie (A i B) i (B i A) jest tym samym zbiorem, więc możesz zacząć od każdego członka A i sprawdzić, czy jest on również w B, * lub * zaczyna się od każdego członek B i sprawdź, czy jest on również w A. Sugeruję z moim pytaniem, że nie musisz sprawdzać dwóch członkostw, ponieważ element ('x') jest już pobrany z jednego z tych zestawów (@Monica właśnie wyjaśniłem to samo). –

7

podanej odpowiedzi są ładne i zadziwiające, ale nie może być problemem w void „s answer a mianowicie:. " Co jeśli jedna z wartości majątkowych celowo do undefined "

Nina 's answer jest dobre (naprawdę fantastyczne), ale ponieważ jesteśmy na krawędzi jutra JavaS CRIPT myślę kopalnia przyzwyczajenie się zbyt złe:

var a = { x: undefined, y: 1, z: 2, a: 10, b: 20, e: 30 } 
 
var b = { x: 0, y: 1, z: 2, a: 10, c: 20, d: 30 } 
 

 
function intersect(o1, o2){ 
 
    return Object.keys(o1).filter(k => k in o2) 
 
} 
 

 
document.write('<pre>' + JSON.stringify(intersect(a, b)) + '</pre>');