首页 > 解决方案 > 如何使用条件窗口而不是基于时间的窗口将整数流拆分为缓冲区?

问题描述

我有一个 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 部分并将流拆分到“无触摸”时刻之间的手指 ID 缓冲区。我也可以这样描述:

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]

标签: c#unity3dobservableunirx

解决方案


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

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;
}

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


推荐阅读