rxjs:地图内部的递归可观察发射

时间:2019-02-27 13:17:10

标签: javascript observable rxjs6

我在尝试在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}
]*/

1 个答案:

答案 0 :(得分:0)

我需要采取的方法是进行重组,以便可以使用mergeMap而不是map-这意味着我在该条件下需要两个可观察对象而不是一个。从那里我只需要重构,以便在mergeMap之后完成到键,元素的映射。

这仍然是我对rxjs的首次尝试,因此我的解释不是很好,而我对该问题的总结也不是很好。重要的是,至少它现在的行为符合预期。

SELECT 
    t.trantype, 
    t.cusip, 
    t.tradedate, 
    COALESCE(
        tbuy.quantity / COUNT(*) OVER(PARTITION BY t.cusip, tbuy.tradedate), 
        t.quantity
    ) quantity
FROM temptable t
LEFT JOIN temptable tbuy 
    ON  t.quantity IS NULL
    AND t.trantype = 'SELL'
    AND tbuy.trantype = 'BUY'
    AND tbuy.cusip = t.cusip
    AND tbuy.tradedate < t.tradedate
    AND NOT EXISTS (
        SELECT 1
        FROM temptable tbuy1
        WHERE 
            tbuy1.trantype = 'BUY'
            AND tbuy1.cusip = t.cusip
            AND tbuy1.tradedate < t.tradedate
            AND tbuy1.tradedate > tbuy.tradedate
    )
ORDER BY t.cusip, t.tradedate, t.trantype