将序列中连续出现的特定数字替换为一次出现

时间:2018-08-03 06:07:39

标签: c# reactive-programming system.reactive

我无法解决此特定问题。 给定顺序:

1  1  2  2  3  3  4  1  1  5  6  7  1  1

我希望将连续出现的1替换为一次出现的1。

1  2  2  3  3  4  1  5  6  7  1

我尝试使用DistinctUntilChanged,但是没有用。

List<int> intList = new List<int>() { 1, 1, 2, 2, 3, 3, 4, 1, 1, 5, 6, 7, 1, 1 };
            IObservable<int> intObsrvr = intList.ToObservable();
            intObsrvr
                .DistinctUntilChanged(x => x == 1)
                .SubscribeConsole();

我得到的输出是:

1,2,1,5,1

我也很好奇这个keySelector的工作原理,因为我无法解释我在这里得到的输出顺序。

4 个答案:

答案 0 :(得分:1)

尝试一下:

var intList = new List<int>() { 1, 1, 2, 2, 3, 3, 4, 1, 1, 5, 6, 7, 1, 1 };
var intObsrvr = intList.ToObservable();

var query =
    intObsrvr
        .Scan(
            new { skip = false, value = int.MinValue },
            (a, x) =>  new { skip = (a.value == 1) && (x == 1) , value = x })
        .Where(x => !x.skip)
        .Select(x => x.value);

我觉得.Scan被低估了。


您还可以使用.Publish / Zip / SelectMany

var query =
    intObsrvr.Publish(
        xs => xs
            .StartWith(int.MinValue)
            .Zip(xs, (z, x) => z == 1 & x == 1 ? new int[] { } : new [] { x })
            .SelectMany(x => x));

选择。


var query =
    intObsrvr.Publish(
        xs => xs
            .StartWith(int.MinValue)
            .Zip(xs, (z, x) => z == 1 & x == 1
                ? Observable.Empty<int>()
                : Observable.Return(x))
            .SelectMany(x => x));

更多选择。

答案 1 :(得分:1)

如果内置方法不符合您的要求,您始终可以创建自己的方法。

满足您需求的DistinctUntilChanged很简单:

public static IEnumerable<T> DistinctUntilChanged<T>(
    this IEnumerable<T> source) 
{
    using (var e = source.GetEnumerator())
    {
        if (!e.MoveNext())
            yield break;

        yield return e.Current;
        var previous = e.Current;

        while (e.MoveNext())
        {
            if (!e.Current.Equals(previous))
            {
                yield return e.Current;
                previous = e.Current;
            }
        }
    }
}

答案 2 :(得分:1)

另一个没有Zip的{​​{1}}变体:

SelectMany

答案 3 :(得分:0)

这是另一种实现方式:

/// <summary>Replaces repeated contiguous occurrences of a specific value
/// with a single occurrence of this value.</summary>
public static IObservable<TSource> DistinctUntilChanged<TSource>(
    this IObservable<TSource> source, TSource value)
{
    var comparer = EqualityComparer<TSource>.Default;
    return source
        .Select((v, i) => (Value: v, Index: i))
        .DistinctUntilChanged(e => comparer.Equals(e.Value, value) ? -1 : e.Index)
        .Select(entry => entry.Value);
}

此实现假定该序列包含少于2,147,483,647个元素,否则它将失败,并显示一个OverflowException。这是因为它比较索引而不是值,并且索引的类型为Int32