[英]How to sort a list that is held as an Observable (RxJS, Angular 2)
[英]Angular2 rxjs sort (observable) list of objects by an observable field
我想按可觀察字段對事物列表進行排序,但無法圍繞可觀察對象進行排序以使其正常工作。 有人知道如何實現這一目標嗎?
初始情況類似於以下內容:
Thing[] things;
interface Thing {
name: Observable<string>
}
<ul>
<li *ngFor="const thing for things">
{{thing.name | async}}
</li>
</ul>
因為我顯然沒有正確描述我的問題:我想要對事物列表進行排序的字段是一個 Observable,而不是一個普通的字符串。 我想通過 websockets 保持該字段的更新,以便正確檢測更改,我必須使用我可以訂閱的 Observable 字段。
感謝您澄清問題,磷。 :)
以下是您可以按照您的要求執行的操作:
// Function to compare two objects by comparing their `unwrappedName` property.
const compareFn = (a, b) => {
if (a.unwrappedName < b.unwrappedName)
return -1;
if (a.unwrappedName > b.unwrappedName)
return 1;
return 0;
};
// Array of Thing objects wrapped in an observable.
// NB. The `thing.name` property is itself an observable.
const thingsObs = Observable.from([
{ id: 1, name: Observable.of('foo') },
{ id: 2, name: Observable.of('bar') },
{ id: 3, name: Observable.of('jazz') }
]);
// Now transform and subscribe to the observable.
thingsObs
// Unwrap `thing.name` for each object and store it under `thing.unwrappedName`.
.mergeMap(thing =>
thing.name.map(unwrappedName => Object.assign(thing, {unwrappedName: unwrappedName}))
)
// Gather all things in a SINGLE array to sort them.
.toArray()
// Sort the array of things by `unwrappedName`.
.map(things => things.sort(compareFn))
.subscribe();
將發出的值記錄到控制台將顯示一個按其unwrappedName
屬性排序的 Thing 對象數組:
[
{ id: 2, name: ScalarObservable, unwrappedName: "bar" },
{ id: 1, name: ScalarObservable, unwrappedName: "foo" },
{ id: 3, name: ScalarObservable, unwrappedName: "jazz" }
]
如果您對此代碼有疑問,請告訴我。
如果我理解正確的話,你想要一個看起來像這樣的對象:
Thing {
name: string;
}
然后,您需要一個 Observable 來保存Thing
數組:
things$: Observable<Thing[]>;
然后,您希望通過屬性(在本例中為name
對thing array
中的thing array
進行排序。 可以這樣做:
...
let sorted$: Observable<Thing[]> = things$.map(items => items.sort(this.sortByName))
...
sortByName(a,b) {
if (a.name < b.name)
return -1;
if (a.name > b.name)
return 1;
return 0;
}
...
最后,就像Toung Le在他的回答中所展示的那樣,像這樣更改您的模板:
<ul>
<li *ngFor="let thing of sorted$ | async">
{{thing.name}} <!--No need async pipe here. -->
</li>
</ul>
您可以使用Observable.map
。 例如:
Observable<Thing[]> things;
sortedThings$ = things.map(items => items.sort()) // Use your own sort function here.
在您的模板中:
<ul>
<li *ngFor="let thing of sortedThings$ | async">
{{thing.name}} <!--No need async pipe here. -->
</li>
</ul>
您可以使用Observable.map
然后sort()
和localeCompare
,它看起來像這樣:
.map(data => ({
label: data.name
}))
.sort((a, b) => a.label.localeCompare(b.label));
使用groupby
運算符(使用它):
const $things = getThings();
$things.pipe(
groupBy(thing => thing.id),
mergeMap(group$ => group$.pipe(
reduce((acc, cur) =>[...acc, cur], [])
))
)
.subscribe(console.log)
這是一個非常簡單的解決方案,一旦您了解.pipe
工作原理以及那里有哪些Operator 。
如果我們使用toArray
運算符將所有項目轉換為數組,並將整個數組作為單個項目通過mergeMap
給mergeMap
運算符,我們將能夠對其進行排序,然后將數組mergeMap
回來。
interface Thing {
name: string;
}
const things: Observable<Thing>;
...
things
.pipe(toArray())
.pipe(mergeMap(_things =>
_things.sort((a, b) =>
a.name.localeCompare(b.name)
)
));
// OR
things.pipe(toArray(), mergeMap(_things =>
_things.sort((a, b) =>
a.name.localeCompare(b.name)
)
));
使用過濾功能更改了排序功能也使其適用於 rxjs 6.6.2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.