如何使用 RxJS 从嵌套的类型化对象数组中查找最大值和最小值?

huangapple go评论86阅读模式
英文:

how to find max min from nested typed object array using RxJS?

问题

以下是已翻译的代码部分:

type DataTableType = {
  name: string;
  series: {
    name: string;
    value: number;
  }[];
}[];

let datatable: DataTableType = [
    {
      name: 'Row 1',
      series: [
        {
          name: 'Series 1',
          value: 7110
        },
        {
          name: 'Series 2',
          value: 8240
        },
        {
          name: 'Series 3',
          value: 2111
        },
        {
          name: 'Series 4',
          value: 3120
        }
      ]
    },
    // ... (其他数据行)
];

function findMax(column: DataTableType) {
  let maxN = column[0].series[0].value;
  of(...column)
    .pipe(
      mergeMap(
        (item: DataTableType[number], i: number) => from(
          [...item.series]
        )
        .pipe(
          max((a, b) => a.value < b.value ? b.value : a.value)
        )
      )
    )
    .subscribe(
      (category: { value: number; }) => {
        maxN = category.value;
      }
    )
  ;
  return maxN;
}

function findMin(column: DataTableType) {
  let minN = column[0].series[0].value;
  of(...column)
    .pipe(
      mergeMap(
        (item: DataTableType[number], i: number) => from(
          [...item.series]
        )
        .pipe(
          min((a, b) => a.value > b.value ? b.value : a.value)
        )
      )
    )
    .subscribe(
      (category: { value: number; }) => {
        minN = category.value;
      }
    )
  ;
  return minN;
}

请注意,这些函数可能不会立即返回最大和最小值,因为它们使用RxJS进行异步操作。如果您在这些函数之后执行其他操作,应该等待它们的异步操作完成,或者可以将操作移到subscribe回调函数内部以确保在获取最大和最小值之后再进行操作。

英文:

given I have this

type DataTableType = {
name: string;
series: {
name: string;
value: number;
}[];
}[];
let datatable: DataTableType = [
{
name: &#39;Row 1&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:7110
},
{
name:&#39;Series 2&#39;,
value:8240
},
{
name:&#39;Series 3&#39;,
value:2111
},
{
name:&#39;Series 4&#39;,
value:3120
}
]
},
{
name: &#39;Row 2&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:6500
},
{
name:&#39;Series 2&#39;,
value:9120
},
{
name:&#39;Series 3&#39;,
value:5123
},
{
name:&#39;Series 4&#39;,
value:8200
}
]
},
{
name: &#39;Row 3&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:-6453
},
{
name:&#39;Series 2&#39;,
value:-9000
},
{
name:&#39;Series 3&#39;,
value:5009
},
{
name:&#39;Series 4&#39;,
value:8900
}
]
},
{
name: &#39;Row 4&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:8567
},
{
name:&#39;Series 2&#39;,
value:4332
},
{
name:&#39;Series 3&#39;,
value:-3111
},
{
name:&#39;Series 4&#39;,
value:-3222
}
]
},
{
name: &#39;Row 5&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:8333
},
{
name:&#39;Series 2&#39;,
value:3234
},
{
name:&#39;Series 3&#39;,
value:-7323
},
{
name:&#39;Series 4&#39;,
value:1544
}
]
},
{
name: &#39;Row 6&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:2112
},
{
name:&#39;Series 2&#39;,
value:3232
},
{
name:&#39;Series 3&#39;,
value:-8231
},
{
name:&#39;Series 4&#39;,
value:1111
}
]
},
{
name: &#39;Row 7&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:-2112
},
{
name:&#39;Series 2&#39;,
value:3232
},
{
name:&#39;Series 3&#39;,
value:8231
},
{
name:&#39;Series 4&#39;,
value:-9111
}
]
},
{
name: &#39;Row 8&#39;,
series: [
{
name:&#39;Series 1&#39;,
value:-2112
},
{
name:&#39;Series 2&#39;,
value:100
},
{
name:&#39;Series 3&#39;,
value:-3
},
{
name:&#39;Series 4&#39;,
value:0
}
]
}
]

I want to find the Max and Min from the datatable with using RxJS, I have done this below to find the Max and Min

function findMax(column: DataTableType) {
let maxN = column[0].series[0].value;
of(...column)
.pipe(
mergeMap(
(item: DataTableType[number], i: number) =&gt; from(
[...item.series]
)
.pipe(
max((a, b) =&gt; a.value &lt; b.value? b.value : a.value)
)
)
)
.subscribe(
(category: { value: number; }) =&gt; {
maxN = category.value;
}
)
;
return maxN;
}
function findMin(column: DataTableType) {
let minN = column[0].series[0].value;
of(...column)
.pipe(
mergeMap(
(item: DataTableType[number], i: number) =&gt; from(
[...item.series]
)
.pipe(
min((a, b) =&gt; a.value &gt; b.value? b.value : a.value)
)
)
)
.subscribe(
(category: { value: number; }) =&gt; {
minN = category.value;
}
)
;
return minN;
}

But whenever I run the functions findMax(datatable) and findMin(datatable) I get max = 0 and min = -2112 of the last element of the object array which is Row 8.

My expected answer should be max = 9120 and min = -9111

Please I need help.

答案1

得分: 1

以下是您要翻译的内容:

The functions given to min and max should behave like the comparator function passed to Array.sort():
>The return value should be a number whose sign indicates the relative order of the two elements: negative if a is less than b, positive if a is greater than b, and zero if they are equal.

Unfortunately, the documentation of RxJS provides this only through examples, i.e. for min() it gives the example:
min((a, b) =&gt; a.age &lt; b.age ? -1 : 1)
Note that min and max work with the same comparison, you don't have to adjust it depending on whether you want min or max. So in your case, it is (a,b) =&gt; a.value - b.value for both.

A second problem in your functions is that you apply the min/max to the steam you generate inside the mergeMap(), so it will be evaluated for each group, instead of the flattened stream. So you will get a result for every Row item, and your variable will be set to each of them, until it is returned with the value from the last iteration.

Instead, apply min/max after the merge, so that you get the smallest/largest value from the whole stream.

Together with the fixed comparator, this gives you:

  let maxN = column[0].series[0].value;
from(column)
.pipe(mergeMap(item =&gt; item.series))
.pipe(max((a, b) =&gt; a.value - b.value))
.subscribe(
(category) =&gt; {
maxN = category.value;
}
)
;
return maxN;
}```
Alternatively, you can also have the `mergeMap` extract the values directly, then you don&#39;t have to use a comparator:
```function findMax(column) {
let maxN = column[0].series[0].value;
from(column)
.pipe(mergeMap(item =&gt; from(item.series).pipe(map(s =&gt; s.value))))
.pipe(max())
.subscribe(
(category) =&gt; {
maxN = category;
}
)
;
return maxN;
}```
<details>
<summary>英文:</summary>
The functions given to min and max should behave like the comparator function passed to [Array.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#syntax):
&gt;The return value should be a number whose sign indicates the relative order of the two elements: negative if `a` is less than `b`, positive if `a` is greater than `b`, and zero if they are equal.
Unfortunately, the documentation of RxJS provides this only through examples, i.e. for [`min()`](https://rxjs.dev/api/index/function/min) it gives the example:

min((a, b) => a.age < b.age ? -1 : 1)

Note that `min` and `max` work with the same comparison, you don&#39;t have to adjust it depending on whether you want min or max. So in your case, it is `(a,b) =&gt; a.value - b.value` for both.
----------
A second problem in your functions is that you apply the `min`/`max` to the steam you generate inside the `mergeMap()`, so it will be evaluated for each group, instead of the flattened stream. So you will get a result for every `Row` item, and your variable will be set to each of them, until it is returned with the value from the last iteration.
Instead, apply `min`/`max` after the merge, so that you get the smallest/largest value from the whole stream.
Together with the fixed comparator, this gives you:

function findMax(column) {
let maxN = column[0].series[0].value;
from(column)
.pipe(mergeMap(item => item.series))
.pipe(max((a, b) => a.value - b.value))
.subscribe(
(category) => {
maxN = category.value;
}
)
;
return maxN;
}


----------
Alternatively, you can also have the `mergeMap` extract the values directly, then you don&#39;t have to use a comparator:

function findMax(column) {
let maxN = column[0].series[0].value;
from(column)
.pipe(mergeMap(item => from(item.series).pipe(map(s => s.value))))
.pipe(max())
.subscribe(
(category) => {
maxN = category;
}
)
;
return maxN;
}


</details>

huangapple
  • 本文由 发表于 2023年7月3日 22:05:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76605535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定