【问题标题】:RXJS groupBy Observable <Object[]>RXJS groupBy Observable <Object[]>
【发布时间】:2018-10-24 05:19:28
【问题描述】:

我有entries$: Observable&lt;BooksOverviewGroup[]&gt;;:

我想按 groupId 对它们进行分组。我试过这样:

groupBy(books => books.map(book => book.groupId)),
 mergeMap(innerObs => innerObs.skip(1).map(books => books.map(book => book.groupTitle)));

但是,它没有用。在这种情况下如何按 groupId 分组? (Observable&lt;Object[]&gt;)

【问题讨论】:

  • 你真的想把它组合成一个更高阶的 observable 吗?还是您实际上的意思是将其转换为组列表的可观察对象?
  • 我想按 GroupID 对它进行分组并将它们作为数组返回。现在我从 Observable 开始(因为 [] groupby 没有让我明白)也许我只需要将这个 Observable 转换为普通数组并使用普通 groupby。你知道怎么把它变成普通数组吗?
  • 你没有回答我的问题。你想要更高阶的 observable(每组发出一个 observable 的 observable)还是发出组的单个 observable?
  • 抱歉,我想看看这两种变体来学习如何处理数据。如果成本太高,我想看看高阶可观察的解决方案。谢谢。
  • 您找到解决方案了吗?我也很困惑为什么 groupBy 给我一个数组所以我不能分组..

标签: angular rxjs observable


【解决方案1】:

你几乎明白了。

尝试在groupBy() 之前使用mergeMap()concatMap()

举个例子:

const people = [
  { name: 'Sue', age: 25 },
  { name: 'Joe', age: 30 },
  { name: 'Frank', age: 25 },
  { name: 'Sarah', age: 35 }
];

of(people) // <- this gets Observable<Object[]>
  .pipe(
    mergeMap(res => res), // <- use concatMap() if you care about the order
    groupBy(person => person.age, p => p.name),
    mergeMap(group => zip(of(group.key), group.pipe(toArray())))
  )
  .subscribe(console.log);

输出:

(2) [25, Array(2)]
(2) [30, Array(1)]
(2) [35, Array(1)]

【讨论】:

  • 非常感谢这个答案,我一直在寻找这个,
  • 这很有趣:) 你能详细说明你的答案吗?
  • 这个答案对我没有帮助。实际上它返回:"TypeError: You provided 'function zipOperatorFunction(source) {"This was what I was looking for
【解决方案2】:

高阶 Observable

如果你想要更高阶的 observable,实际上可以使用groupByrxjs 运算符。

const data = [
  {groupId: "foo", value: 1},
  {groupId: "foo", value: 3},
  {groupId: "foo", value: 5},
  {groupId: "bar", value: 42},
  {groupId: "bar", value: 1337},
];

from(data).pipe(
  groupBy(item => item.groupId)
)
  .subscribe(console.log);

这将导致每个组发出一个可观察对象的可观察对象,并且在每个内部可观察对象上,将发出相应的项目。

可观察的组

如果您想要一个简单地发出组的 observable,那么这实际上与 rxjs 或其 groupBy 运算符无关。相反,这只是一个关于如何在 Javascript 中对数组进行分组的基本问题。

对此没有内置方法,但像 lodash 这样的库带有这样的功能。您也可以手动完成:

const data = [
  {groupId: "foo", value: 1},
  {groupId: "foo", value: 3},
  {groupId: "foo", value: 5},
  {groupId: "bar", value: 42},
  {groupId: "bar", value: 1337},
];

const groupBy = (data, keyFn) => data.reduce((agg, item) => {
  const group = keyFn(item);
  agg[group] = [...(agg[group] || []), item];
  return agg;
}, {});

of(data).pipe(
  map(data => groupBy(data, item => item.groupId))
)
  .subscribe(console.log);

这将对整个数据集发出一次,但会发出

{
  "foo":[
    {"groupId":"foo","value":1},
    {"groupId":"foo","value":3},
    {"groupId":"foo","value":5}
  ],
  "bar":[
    {"groupId":"bar","value":42},
    {"groupId":"bar","value":1337}
  ]
}

【讨论】:

  • 感谢您的帮助和时间。但是,对于高阶 Observable: from(data).pipe( groupBy(item => item.groupId) ) 我之前尝试过,但它不起作用,因为我有一个 Observable 数组,不仅仅是普通对象喜欢对象;这是一个 Object[] groupId 在 item 中是未知的,因为在这种情况下 item 是 object [] 的数组但是如果我走得更远: groupBy(books => books.map(book => book.groupId)) 它认为我需要数组作为键,结果是错误的。我将尝试观察组。
【解决方案3】:

只需使用groupByoperator,然后将它们全部合并。

$data.pipe(
    groupBy(book => book.groupId),
    mergeMap(group => group.pipe(toArray()))
)
.subscribe(console.log)

【讨论】:

  • 它不适用于 Observable。我得到了一个数组作为键。
  • Rxjs 6.3.2 + Angular 6.1.8 -> @dunaskdunsay 所说的,你得到了一个数组。在下面的代码示例中,打字稿给出了错误'属性年龄不存在类型'{名称:字符串;年龄:数字; }[]'const people = [{ name: 'Sue', age: 25 }, { name: 'Joe', age: 30 }, { name: 'Frank', age: 25 }, { name: 'Sarah', age: 35 }]; const source = of(people); const example = source.pipe(groupBy(p =&gt; p.age)); example.subscribe(val =&gt; console.log(val));
【解决方案4】:
const data = [
    { groupId: "foo", value: 1 },
    { groupId: "foo", value: 3 },
    { groupId: "foo", value: 5 },
    { groupId: "bar", value: 42 },
    { groupId: "bar", value: 1337 },
];

of(data).pipe(
    mergeMap(res => res),
    groupBy(item => item.groupId),
    mergeMap(obs => {
        return obs.pipe(
            toArray(),
            map(items => {
                return { [obs.key]: items }
            })
        )
    }), toArray()
).subscribe(map((groupResponse) => {
    let groups = {};
    groupResponse.forEach((item) => { groups = { ...groups, ...item }; });
    console.log(groups);
});

输出将是

{
    "foo": [{ "groupId": "foo", "value": 3 }, { "groupId": "foo", "value": 5 }],
    "bar": [{ "groupId": "bar", "value": 42 }, { "groupId": "bar", "value": 1337 }]
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 2016-12-18
    • 2020-11-17
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    相关资源
    最近更新 更多