我有一个带有关键字的 ReactiveList。用户可以从该列表中添加或删除关键字。应用程序需要验证用户是否输入了关键字之一。 已经有一篇类似的文章,但它没有考虑灵活的列表: Using Reactive Extension for certain KeyPress sequences?
var keyElements = new ReactiveList<KeyElement>();
IObservable<IObservable<int>> rangeToMax = Observable.Merge(keyElements.ItemsAdded, keyElements.ItemsRemoved).Select(obs => Observable.Range(2, keyElements.Select(ke => ke.KeyTrigger.Length).Max()));
IObservable<IObservable<string>> detectedKeyTrigger = rangeToMax
.Select(n => _keyPressed.Buffer(n, 1))
.Merge().Where(m => keyElements.Where(ke => ke.KeyTrigger == m).Any());
//Here I want to end up with IObservable<string> instead of IObservable<IObservable<string>>
每当 react 列表中的元素发生变化时,我可以通过重新分配 detectorKeyTrigger 来摆脱外部 IObservable,但随后我会丢失所有订阅。 那么,我怎样才能得到一个字符串的 Observable 呢?
最佳答案
首先,都是 Max
和Any
具有分别采用选择器和谓词的重载。这消除了 Select
的需要.
接下来,我更改了Observable.Merge
使用Changed
ReactiveList
的属性(property)这是 INotifyCollectionChanged
的 Rx 版本。我还更改了Select
产生 IEnumerable
的int
代替;只是感觉更正确™。
var keyElements = new ReactiveList<KeyElement>();
IObservable<IEnumerable<int>> rangeToMax = keyElements.Changed
.Select(_ => Enumerable.Range(2, keyElements.Max(keyElement => keyElement.KeyTrigger.Length));
IObservable<IObservable<string>> detectedKeyTrigger = rangeToMax.
.Select(range => range
.Select(length => _keyPressed.Buffer(length, 1).Select(chars => new string(chars.ToArray()))) // 1
.Merge() // 2
.Where(m => keyElements.Any(ke => ke.KeyTrigger == m)) // 3
.Switch(); // 4
- 创建
IObservable<string>
发出最后一个n
用户输入的字符。为组合的每个可能长度创建这样的可观察量 - 合并
IEnumerable<IObservable<string>>
中的可观测值合二为一Observable<string>
- 仅让字符串符合
KeyTrigger
之一通过 - 如
rangeToMax.Select
产生IObservable<IObservable<string>>
我们使用Switch
只订阅最新的IObservable<string>
IObservable<IObservable<string>>
产生。
关于system.reactive - 验证用户是否从具有响应式扩展的响应式列表中键入了单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46402818/