簡體   English   中英

rxjs:地圖內部的遞歸可觀察發射

[英]rxjs: recursive Observable emission inside map

我試圖在rxjs中以遞歸方式對數據進行分組,這有點麻煩。 在不同的用例中似乎有很多很好的例子,但是我似乎無法重構代碼以適應我的需求。

我可以推斷出的中心問題是,在我的地圖運算符中,我有一個條件收益,它是不可觀察的或可觀察的。 有什么方法可以重構以解決這種差異?

理想情況下,此函數將原始的“平面”數組按作為cols參數傳入的任意數量的列進行分組。

每次滿足條件時,它都會以{鍵:col_name,元素:[... col_elements]}的格式追加到數組中,其中元素將是具有相同格式的另一個元素數組,或者是元素的直接列表。

下面的函數僅在對列進行一次分組時起作用(因此永遠不需要map中的可觀察對象發出)。

//group data n times based on passed string[] of column attributes
  group_data(elements: Observable<any>, cols: string[], index=0) : Observable<any> {
    let col = cols[index]

    return elements.pipe(
      //groupby column value
      RxOp.groupBy((el:any) => this.get_groupingValue(el, col)),

      //place key inside array
      RxOp.mergeMap((group) => group.pipe(
        RxOp.reduce((acc, cur) => [...acc, cur], ["" + group.key]))
      ),
      // map to key:group
      RxOp.map((arr:any) =>

          cols.length <= index + 1?
          // no more grouping req
          { 'key': arr[0], 'elements': arr.slice(1) } :

          //group recursively, returns Observable instead of array:(
          { 'key': arr[0], 'elements':
            this.group_data(from(arr.slice(1)), cols, index + 1)
              .pipe(
                RxOp.tap(t=> console.log(t)), // not logged
                RxOp.reduce((acc, val) => [...acc, val], [])

              )
          }),
      RxOp.toArray()
    )
  }

//simplified data example:

data = [{id: 'idA', type: 'project', parents: null },
 {id: 'idB', type: 'project', parents: null },
 {id: 'idC', type: 'episode', parents: ['idA'] },
 {id: 'idD', type: 'episode', parents: ['idB'] },
 {id: 'idE', type: 'scene', parents: ['idA', 'idC'] },
 {id: 'idF', type: 'scene', parents: ['idB', 'idD'] }] 

// 1 column passed works correctly as below

group_data(elements: from(data), ['project'])

/* outputted data:
[{key: 'idA', 
  elements: [ {id: 'idC', type: 'episode', parents: ['idA'] },
              {id: 'idE', type: 'scene', parents: ['idA', 'idC'] }]},
{key: 'idB', 
  elements: [ {id: 'idD', type: 'episode', parents: ['idA'] },
              {id: 'idF', type: 'scene', parents: ['idA', 'idC'] }]},

{key: null,
  elements: [ {id: 'idA', type: 'project', parents: [] }
              {id: 'idB', type: 'project', parents: [] }]}
]
*/

// 2 columns not working correctly
group_data(elements: from(data), ['project', 'episode'])
/*[{key: 'idA', 
  elements: Observable},
{key: 'idB', 
  elements: Observable},
{key: null, 
  elements: Observable}
]*/

我需要采取的方法是進行重組,以便可以使用mergeMap而不是map-這意味着我在該條件下需要兩個可觀察對象而不是一個。 從那里我只需要重構,以便在mergeMap之后完成到鍵元素的映射。

這仍然是我對rxjs的首次嘗試,因此我的解釋不是很好,而我對該問題的總結也不是很好。 重要的是,至少其行為符合現在的預期。

//group data n times based on passed string[] of column attributes
  group_data(elements: Observable<any>, cols: string[], index=0) : Observable<any> {
    let col = cols[index]

    let grouping = elements.pipe(
      //groupby column value
      RxOp.groupBy((el:any) => this.get_groupingValue(el, col)),

      //place key inside array
      RxOp.mergeMap((group) => group.pipe(
        RxOp.reduce((acc, cur) => [...acc, cur], ["" + group.key]))
      )
    )


    return grouping.pipe(
      RxOp.mergeMap((arr) =>
        (
        cols.length <= (index +1) ?

        //no more grouping required
        of(arr.slice(1)) : 

        //group again
        this.group_data(from(arr.slice(1)), cols, index + 1))

        // reduce result and put the key back in
        .pipe(
          RxOp.reduce((acc, cur) => [...acc, cur], ["" + arr[0]])
        )
      ),

      // map to key:group
      RxOp.map(arr => ({
          key: arr[0],
          elements: arr.slice(1)
        })
      ),
      RxOp.toArray()
    )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM