English 中文(简体)
如何根据第二流将可观察的溪流分成几个层?
原标题:How to split an Observable stream in chunks, dependent on second stream?

我认为,这是一件容易的事,但现在我的大脑正在融洽。

The problem

Given the following IObservable<int> Stream: 1 1 0 0 0 1 0 0 1 0 1

我想将其分为<代码>。 IObservable<IEvidable<int>> 表格的简化

<0>0

<0>0

<0>0

只要有零件,就只添加到可以计算的数字中,当出现1份清单时,就开始编制新的清单;这是对我的实际问题所作的比较更清洁的定义。

My approach so far

我认为,一个很好的解决办法是首先将其转换成<代码>。 IObservable<IObservable<int>>via the Window methods and subsequently use ToEvidable, but somehow I no it do it do it. I used Zip and Skip(1) to have a diff to final elements, I used Dis本untilChanged(. 我把我所尝试的所有变数都留给你......

也许我最接近的是这一法典:

int[] ints = new[] { 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1 };
var observable = Observable.Interval(TimeSpan.FromMilliseconds(1000)).Take(11).Select(i => ints[i]);

Subject<int> subject = new Subject<int>();
observable.Subscribe(subject);

var observableDiff = subject.Skip(1).Zip(subject, (n, p) => new { Previous = p, Next = n });
var windows = observable.Window(() => observableDiff.Where(x => x.Next == 1));

int index = 0;
windows.Subscribe(window =>
{
  Console.WriteLine(string.Format("new window [{0}] ", index++));
  window.Subscribe(number => Console.WriteLine(number));
});

这种回报是好的,但不幸的是,它最终坠毁。

new window [0]
1
new window [1]
1
0
0
0
new window [2]
1
0
0
new window [3]
1
0
new window [4]
new window [5]
new window [6]
new window [7]
new window [8]
new window [9]
<-- it goes on here until window ~ [80] with a stackoverflow exception

如果在我的法典中出现这种ug,我会达到......。

任何帮助都将受到高度赞赏。

Edit:我使用Rx-Experimental,但并没有改变(由LinqPad检查)。 Also 删除了这个主题,它没有影响任何内容。 似乎采用我的新做法(Edit2),你需要一个主题,否则,窗户的开端是完全令人望而却。

Edit2:稍微改变了问题,以更好地突出我的问题,令人不安。 我也更新了解决办法。

最佳回答

This worked for me:

var ints = (new[] { 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1 }).ToObservable();

var result =
    ints
        .Publish(ns =>
            ns
                .Where(n => n == 1)
                .Select(n =>
                    ns.TakeWhile(m => m == 0).StartWith(n).ToArray())
        ).Merge();

I ve used Publish in to ensure that the ints Observable is treatment as “hot” than “cold”.

My results look like this:

“grouped

问题回答

封面的<代码>Buffer似乎与你的需要相当接近。 来文方与Buffer呼吁之间的中间订货,将使你们能够看到你需要的结关。

IObservable<IList<T>> Buffer<T>(IObservable<T> source, 
                                Func<T, bool> startNew)
{
    return Observable.Create<IList<T>>(
        obs =>
        {
            var starts = new Subject<Unit>();
            return source.Do(v => 
                             {
                                if (startNew(v))
                                    starts.OnNext(Unit.Default);
                             })
                         .Buffer(() => starts)
                         .Where(v => v != null && v.Count > 0)
                         .Subscribe(obs);
        });
}

Ok也是以下几个方面的良好答案::

詹姆斯·米勒斯建议:

var source = new[] { 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1 }.ToObservable();

var windows = 
from window in source
  .Buffer(2,1) // create an overlapping buffer with 2 items
  .Publish(xs => xs.Window(() => xs.Where(x => x.Last() == 1))) // close the window if the 2nd item is == 1
from result in window
  .Select(buffer => buffer.First()) // we are only interested in the first item (the 2nd item might be the 1!)
  .ToArray() // aggregate the results of the window
where result.Any() // filter out final (empty) window
select result;

int index = 0;
windows.Subscribe(window =>
{
  Console.WriteLine(string.Format("new window [{0}] ", index++));
  foreach(var x in window)Console.WriteLine(x);
});

Dave Sexton建议从上使用Parser类别。 追溯性延伸(Rxx)的延伸,看来是一种更为审慎的做法:

using Rxx.Parsers.Reactive.Linq;

public sealed class SplitLab : BaseConsoleLab
{
    protected override void Main()
    {

        var xs = Observable.Generate(
            new[] { 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1 }.GetEnumerator(),
            e => e.MoveNext(),
            e => e,
            e => (int) e.Current,
            e => TimeSpan.FromSeconds(.5));

        var query = xs.Parse(parser =>
            from next in parser
            let one = next.Where(value => value == 1)
            let other = next.Not(one)
            let window = from start in one
                        from remainder in other.NoneOrMore()
                        select remainder.StartWith(start)
            let windowAsString = window.Join()
            select windowAsString);

        using (query.Subscribe(TraceLine))
        {
            WaitForKey();
        }
    }
}

很多路要走。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签