将序列中连续出现的特定数字替换为单个出现的特定数字
Replace consecutive occurrences of a particular number in the sequence with a single occurrence of it
我无法解决这个特殊问题。
给定序列:
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 是如何工作的,因为我无法解释我在这里得到的输出序列。
试试这个:
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));
更多选择。
如果内置方法不符合您的要求,您始终可以创建自己的方法。
满足您需求的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;
}
}
}
}
没有SelectMany
的另一个Zip
变种:
var observable = new List<int> { 1, 1, 2, 2, 3, 3, 4, 1, 1, 5, 6, 7, 1, 1 }
.ToObservable();
observable.StartWith(int.MinValue).Zip(observable, (previous, current) => (previous, current))
.Where(t => t.current != 1 || t.current != t.previous)
.Select(t => t.current);
这是另一个实现:
/// <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
.
我无法解决这个特殊问题。 给定序列:
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 是如何工作的,因为我无法解释我在这里得到的输出序列。
试试这个:
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));
更多选择。
如果内置方法不符合您的要求,您始终可以创建自己的方法。
满足您需求的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;
}
}
}
}
没有SelectMany
的另一个Zip
变种:
var observable = new List<int> { 1, 1, 2, 2, 3, 3, 4, 1, 1, 5, 6, 7, 1, 1 }
.ToObservable();
observable.StartWith(int.MinValue).Zip(observable, (previous, current) => (previous, current))
.Where(t => t.current != 1 || t.current != t.previous)
.Select(t => t.current);
这是另一个实现:
/// <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
.