2016-12-21 3 views
4

Ich habe 3 beobachtbare Arrays wie unten.Kombinieren Sie mehrere beobachtbare Arrays in ein neues Objekt-Array

persons = [ 
    { 
     "firstName":"john", 
     "lastName":"public", 
     "locationID":"1", 
     "departmentID":"100" 
    }, 
    { 
     "firstName":"sam", 
     "lastName":"smith", 
     "locationID":"2", 
     "departmentID":"101" 
    } 
] 

departments = [{"departmentID": "100", 
       "name": "development" 
       }, 
       {"departmentID": "101", 
       "name": "sales" 
       }] 

locations = [{"locationID": "1", "name": "chicago"}, 
       {"locationID":"2", "name": "ny"}] 

Ich versuche, diese 3 in unten Ergebnis zu kombinieren,

result = [ 
    { 
     "firstName":"john", 
     "lastName":"public", 
     "location":"development", 
     "department":"sales" 
    }, 
    { 
     "firstName":"sam", 
     "lastName":"smith", 
     "location":"ny", 
     "department":"sales" 
    } 
] 

Um das gewünschte Ergebnis zu erhalten, habe ich Kartenfunktion auf Personen beobachtbar geben neues Objekt-Array verwendet.

this.store<Person>('persons') 
.map(function(person){ 
    let p = new personDetail() 
    p.firstName = person.firstName, 
    p.lastName = person.lastName 
    return p; 
}) 

PersonDetail Objekt hat firstName, lastName, location und department Eigenschaften. Wie mache ich einen Blick in die beobachtbaren Abteilungen und bekomme eine passende Zeile für departmentID, um den Abteilungsnamen zu erhalten?

Ich bin neu in der Bibliothek rxjs, lassen Sie mich wissen, ob es einen besseren Weg gibt, das gewünschte Ergebnis zu erzielen.

Antwort

5

Da Sie sehr wahrscheinlich, dass Listen von Abteilungen und Standorte von einem Remote-Service (stellen eine weitere HTTP-Anforderung) holen wollen werde ich es sofort mit Observablen auch tun würde.

Observable.from(persons) 
    .mergeMap(person => { 
     let department$ = Observable.from(departments) 
      .filter(department => department.departmentID == person.departmentID); 

     let location$ = Observable.from(locations) 
      .filter(location => location.locationID == person.locationID); 

     return Observable.forkJoin(department$, location$, (department, location) => { 
      return { 
       'firstName': person.firstName, 
       'lastName': person.lastName, 
       'location': location.name, 
       'department': department.name, 
      }; 
     }); 
    }) 
    .toArray() 
    .subscribe(result => console.log(result)); 

Diese Drucke zu trösten:

[ { firstName: 'john', 
    lastName: 'public', 
    location: 'chicago', 
    department: 'development' }, 
    { firstName: 'sam', 
    lastName: 'smith', 
    location: 'ny', 
    department: 'sales' } ] 

Es ist zwei Observable department$ und location$, die mit filter() Operator gefiltert werden mit passender ID den einzigen Artikel zu erhalten. Dann wartet forkJoin() Operator, bis beide von ihnen abgeschlossen sind. Der Operator mergeMap() wiederholt dann den von forkJoin() zurückgegebenen Wert erneut. Am Ende mit toArray() sammeln wir alle Elemente in einem einzigen Array.

Anstelle von Observable.from(...) können Sie den Service verwenden, den Sie benötigen (z. B. http.get(...)).

Siehe Live-Demo: https://jsbin.com/nenekup/4/edit?js,console

ähnliche Fragen: Merge subarrays using Observables und Subscribing to a nested Observable

+0

Danke, ich konnte es mit gabelJoin arbeiten. – Yousuf

2

Es ist nicht klar, was genau Ihre Observablen aussenden, also habe ich zwei Optionen in Betracht gezogen.

let persons = [ 
    { 
     "firstName":"john", 
     "lastName":"public", 
     "locationID":"1", 
     "departmentID":"100" 
    }, 
    { 
     "firstName":"sam", 
     "lastName":"smith", 
     "locationID":"2", 
     "departmentID":"101" 
    } 
]; 

let departments = [ 
    {"departmentID": "100", "name": "development"}, 
    {"departmentID": "101", "name": "sales"} 
]; 

let locations = [ 
    {"locationID": "1", "name": "chicago"}, 
    {"locationID": "2", "name": "ny"} 
]; 

// Option 1: first observable emits persons one by one, 
// locations and departments are emitted as whole arrays. 
let o1: any = Observable.from(persons); 
let o2: any = Observable.of(departments); 
let o3: any = Observable.of(locations); 

o1.withLatestFrom(o2, o3, (p, d, l) => { 
    // here it is probably better to convert array to some kind of map or dictionary, 
    // but I'm only showing Rxjs concept of doing such things. 
    let location = l.find(c => c.locationID === p.locationID); 
    let department = d.find(c => c.departmentID === p.departmentID); 
    return { 
     firstName: p.firstName, 
     lastName: p.lastName, 
     location: location ? location.name : "", 
     department: department ? department.name : "" 
    }; 
}).subscribe((f) => { 
    console.log(f); 
}); 

// Option 2: all observables emit elements one by one. 
// In this case we need to convert departments and locations to arrays. 
o1 = Observable.from(persons); 
o2 = Observable.from(departments); 
o3 = Observable.from(locations); 

o1.withLatestFrom(o2.toArray(), o3.toArray(), (p, d, l) => { 
    // this part of code is exactly the same as in previous case. 
    let location = l.find(c => c.locationID === p.locationID); 
    let department = d.find(c => c.departmentID === p.departmentID); 
    return { 
     firstName: p.firstName, 
     lastName: p.lastName, 
     location: location ? location.name : "", 
     department: department ? department.name : "" 
    }; 
}).subscribe((f) => { 
    console.log(f); 
}); 
2

Ich denken, die RxJS .zip Operator Ihr Freund hier sein kann.

Soweit ich verstehe, gibt .zip so ...

.zip(
    Observable.from[array1].switchMap(// map to http response here), 
    Observable.from[array2].switchMap(// map to http response here), 
    Observable.from[array3].switchMap(// map to http response here) 
).map((valueFromArray1, valueFromArray2, valueFromArray3) { 
    // Create your object here 
}) 

So etwas! Hoffentlich bringt dich das auf die richtige Spur.

. Zip sollte das erste Mal, wenn alle 3 emittiert haben (und es wird ein zweites Mal emittieren, wenn alle drei Strom zweimal ausgestrahlt haben, usw.) - In Ihrem Szenario erwarte ich alle drei Stream nur einmal emittieren, was es macht ein einfacher Fall für .zip

+0

interessant, wusste ich nicht über Zip-Funktion. Ich konnte es mit Hilfe von forkJoin funktionieren lassen, wie Martin vorgeschlagen hat. – Yousuf

Verwandte Themen