为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用条件窗口而不是基于时间的窗口将整数流分割到缓冲区中?

如何使用条件窗口而不是基于时间的窗口将整数流分割到缓冲区中?

C#
蓝山帝景 2023-07-09 17:45:59
我有一个 Observable 返回整数,如下所示:1, 1, 1, 1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0如何将此 Observable 转换为返回这些整数的数组,而不是按基于时间的窗口而是按基于值的窗口拆分流?这些整数是 Unity Update 事件中 Touch 的 FingerId。对于这项任务来说并不是那么重要,但为了解释为什么我需要它,我必须提供这些详细信息。-1 表示不触摸。这就是差距。我需要删除那些 -1 部分,并将流拆分到“无触摸”时刻之间的 FingerId 缓冲区。我也可以这样描述:Touch0, Touch0, Touch0, no Touch, no Touch, Touch1存在整数或其他类型并不重要。只需将流拆分为缓冲区,删除“窗口值”。这是我的代码,如果有帮助的话:var leftSideTouchStream = Observable.EveryUpdate()            .Scan(-1, (id, _) =>            {                if (id < 0)                {                    var leftSideTouches = Input.touches                        .Where(t =>                            t.phase == TouchPhase.Began                            && t.position.x < Screen.width / 2                        );                    return leftSideTouches.Any() ? leftSideTouches.First().fingerId : -1;                }                else                {                    var touchEnded = Input.touches                        .Any(t =>                            t.fingerId == id &&                            (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled)                        );                    return touchEnded ? -1 : id;                }            })            .Select(id =>            {                return Input.touches                    .Where(t => t.fingerId == id)                    .Select(t => new Nullable<Touch>(t))                    .FirstOrDefault();            });我需要与 Buffer 函数给出的行为完全相同的行为,但正如我所说,根据值而不是时间。如果我有这个流:1, 1, 1, 1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0并且“窗口值”为-1,则预期结果为:[1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0]
查看完整描述

2 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

可能存在一些更好的魔法解决方案,但我想最直接的解决方案是这样的


private static int[][] GetArrays(int[] intputArray)

{

    // use lists for dynamically adding elements

    var outputLists = new List<List<int>>();


    // initialize with the ignored value

    var lastValue = -1;


    // iterate over the inputArray

    foreach (var value in intputArray)

    {

        // skip -1 values

        if (value < 0)

        {

            lastValue = -1;

            continue;

        }


        // if a new value begin a new list

        if (lastValue != value)

        {

            outputLists.Add(new List<int>());

        }


        // add the value to the current (= last) list

        outputLists[outputLists.Count - 1].Add(value);


        // update the lastValue

        lastValue = value;

    }


    // convert to arrays

    // you could as well directly return the List<List<int>> instead

    // and access the values exactly the same way

    // but since you speak of buffers I guess you wanted arrays explicitely

    var outputArrays = new int[outputLists.Count][];

    for (var i = 0; i < outputLists.Count; i++)

    {

        outputArrays[i] = outputLists[i].ToArray();

    }


    return outputArrays;

}

如此呼唤


var arrays = GetArrays(new int[]{1, 1, 1, 1, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0});

应该导致


arrays[0] => [1, 1, 1, 1]

arrays[1] => [0, 0, 0, 0]

arrays[2] => [0, 0, 0]    

因为您似乎更想动态地一一添加值,所以我根本不会使用数组,而是使用类似的东西


private List<List<int>> arrays = new List<List<int>>();


private int lastValue;


private void AddValue(int value)

{

    // skip -1 values

    if (value < 0)

    {

        lastValue = -1;

        return;

    }


    // if a new value begin a new list

    if (lastValue != value)

    {

        arrays.Add(new List<int>());

    }


    // add the value to the current (= last) list

    arrays[outputLists.Count - 1].Add(value);


    // update the lastValue

    lastValue = value;

}

我的意思是你必须存储在某个地方的东西


查看完整回答
反对 回复 2023-07-09
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

不幸的是我没有找到任何开箱即用的解决方案,所以我想出了我自己的 Observable 实现:


using System;

using System.Collections.Generic;

using UniRx;


public static class ObservableFunctions

{

    public static IObservable<T[]> BufferWhen<T>(this IObservable<T> source, Predicate<T> predicate)

    {

        return Observable.Create<T[]>(observer =>

        {

            List<T> buffer = new List<T>();


            source.Subscribe(

                t =>

                {

                    if (predicate(t))

                    {

                        buffer.Add(t);

                    }

                    else

                    {

                        if (buffer.Count > 0)

                        {

                            observer.OnNext(buffer.ToArray());

                            buffer = new List<T>();

                        }

                    }

                },

                e =>

                {

                    observer.OnError(e);

                },

                () =>

                {

                    observer.OnCompleted();

                }

            );


            return Disposable.Empty;

        });

    }

}

幸运的是,事情非常简单。比在 Google 中搜索适当的功能更简单...


查看完整回答
反对 回复 2023-07-09
  • 2 回答
  • 0 关注
  • 101 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信