Reputation: 1810
I have a simple interface with 2 properties k,v (key, value).
export interface KV {
k: string;
v: any
}
This is a base for variety of nested objects of the same type - KV, where v: may contain nested sub-objects of KV and finally arriving to last/leaf object of the tree where v: is string - not of KV type.
Example: (the hierarchy is reversed in this example - the last table is on top -contains the entries where v (value) is string. The following nodes are parent nodes, bottom node is the root node.
const tableC2: KV[] = [
{ k: 'TXT1', v: 'text 1'},
{ k: 'TXT2', v: 'text 2'},
{ k: 'TXT3', v: 'text 3'},
....
];
const tableB1: KV[] = [
{ k: 'C1', v: tableC1},
{ k: 'C2', v: tableC2}, // <--- tableC2 above
{ k: 'C3', v: tableC3},
....
];
const tableA: KV[] = [
{ k: 'A1', v: tableA1},
{ k: 'A2', v: tableA2},
{ k: 'B1', v: tableB1}, // <--- tableB1 above
....
]
Now, having object: tableA as the initial data source set as Observable:
tbl$ = of(tableA);
What would be the most efficient way to set up async / Observable to search the tree hierarchy for a key e.g. key = 'TXT3' and get its v/value - 'text 3', so we can place the observable in the Angular template using the | async pipe?
In a regular / sync approach I have something like this:
private findText(nodes: KV[], key: string): any {
let d: KV[];
for (let n of nodes) {
// navigate to last child node, where v
// is no longer of another KV (k,v) type
while(n.hasOwnProperty('k') && n.hasOwnProperty('v')) {
d = n.v;
n = n.v;
}
let result = d.find(e => e.k === key);
if (result) {
return result.v;
}
}
return undefined;
}
This works OK.
How do we make this function async?
Something like this ( but this is just an idea and I get lost at more complex levels):
public findText(nodes$: Observable<KV[]>, key: string): Observable<any> {
return nodes$.pipe(switchMap(e =>
e.forEach(n =>
n.v.filter(v => ( ! v.hasOwnProperty('k') && ! v.hasOwnProperty('v')))
.filter(t => (t === key))
.map(r => r.v))));
}
Upvotes: 0
Views: 274
Reputation: 9134
You can still use the sync approach.
public findText(nodes$: Observable<KV[]>, key: string): Observable<any> {
return nodes$.pipe(map(nodes => findTextSync(nodes, key)));
}
Upvotes: 1