C# 是否有一个像Scan但让';让我返回一个可观察的<;TResult>;而不是IObservable<;t来源>;?
在这个纯粹为了实践而虚构的示例中,我想返回以下内容:C# 是否有一个像Scan但让';让我返回一个可观察的<;TResult>;而不是IObservable<;t来源>;?,c#,system.reactive,C#,System.reactive,在这个纯粹为了实践而虚构的示例中,我想返回以下内容: var admissionObservable = Observable .FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted") .Timestamp() .Buffer(2) .Where(pair => pair[1].Timestamp - pair[0].Timesta
var admissionObservable = Observable
.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted")
.Timestamp()
.Buffer(2)
.Where(pair => pair[1].Timestamp - pair[0].Timestamp <= timeSpan)
.Select(pair => new JoiningData
{
Students = Tuple.Create(pair[0].Value.EventArgs.Student, pair[1].Value.EventArgs.Student),
School = pair[0].Value.EventArgs.School,
Interval = pair[1].Timestamp - pair[0].Timestamp
});
如果两个学生在指定的时间段内加入一所学校,比如说2秒钟,那么我需要一个数据结构,返回两个学生、他们加入的学校以及他们加入之间的时间间隔
var admissionObservable = Observable
.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted")
.Timestamp()
.Buffer(2)
.Where(pair => pair[1].Timestamp - pair[0].Timestamp <= timeSpan)
.Select(pair => new JoiningData
{
Students = Tuple.Create(pair[0].Value.EventArgs.Student, pair[1].Value.EventArgs.Student),
School = pair[0].Value.EventArgs.School,
Interval = pair[1].Timestamp - pair[0].Timestamp
});
我一直在这样想:
class Program
{
static void Main(string[] args)
{
ObserveStudentsJoiningWithin(TimeSpan.FromSeconds(2));
}
static void ObserveStudentsJoiningWithin(TimeSpan timeSpan)
{
var school = new School("School 1");
var admissionObservable =
Observable.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted");
var observable = admissionObservable.TimeInterval()
.Scan((current, next) =>
{
if (next.Interval - current.Interval <= timeSpan)
{
// But this won't work for me because
// this requires me to return a TSource
// and not a TResult
}
});
var subscription = observable.Subscribe(TimeIntervalValueHandler);
school.FillWithStudentsAsync(10, TimeSpan.FromSeconds(3));
school.FillWithStudentsAsync(8, TimeSpan.FromSeconds(1));
Console.WriteLine("Press any key to exit the program");
Console.ReadKey();
subscription.Dispose();
}
}
var admissionObservable = Observable
.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted")
.Timestamp()
.Buffer(2)
.Where(pair => pair[1].Timestamp - pair[0].Timestamp <= timeSpan)
.Select(pair => new JoiningData
{
Students = Tuple.Create(pair[0].Value.EventArgs.Student, pair[1].Value.EventArgs.Student),
School = pair[0].Value.EventArgs.School,
Interval = pair[1].Timestamp - pair[0].Timestamp
});
类程序
{
静态void Main(字符串[]参数)
{
观察者在(从秒(2)开始的时间跨度)内进行观察;
}
静态void ObserveStudentsJoiningWithin(TimeSpan TimeSpan)
{
var学校=新学校(“学校1”);
可观察的风险值=
可观察。从事件模式(学校,“学生入学”);
var可观测=可观测的容许。时间间隔()
.Scan((当前,下一个)=>
{
if(next.Interval-current.Interval
对于成对比较(原始-将当前项目与下一个项目一起投影),您可以使用一种方法构建成对序列
为了找出学生之间的间隔,使用instead of方法可能更有用,因为下面的行next.interval-current.interval Tuple.Create(a,b))
.Where(pair=>pair.Item2.Timestamp-pair.Item1.Timestamp new JoiningData
{
Students=Tuple.Create(pair.Item1.Value.EventArgs.Student,pair.Item2.Value.EventArgs.Student),
学校=pair.Item1.Value.EventArgs.School,
间隔=pair.Item2.Timestamp-pair.Item1.Timestamp
});
以下是我所做的:
var admissionObservable = Observable
.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted")
.Timestamp()
.Buffer(2)
.Where(pair => pair[1].Timestamp - pair[0].Timestamp <= timeSpan)
.Select(pair => new JoiningData
{
Students = Tuple.Create(pair[0].Value.EventArgs.Student, pair[1].Value.EventArgs.Student),
School = pair[0].Value.EventArgs.School,
Interval = pair[1].Timestamp - pair[0].Timestamp
});
static void ObserveStudentsJoiningWithin(TimeSpan timeSpan)
{
var school = new School("School 1");
var admissionObservable =
Observable.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted");
var observable = admissionObservable.TimeInterval()
.Scan<TimeInterval<EventPattern<StudentAdmittedEventArgs>>, StudentPair>(null, (previousPair, current) =>
{
Debug.Print(string.Format($"Student joined after {current.Interval.TotalSeconds} seconds, timeSpan = {timeSpan.TotalSeconds} seconds"));
var pair = new StudentPair();
if (previousPair == null)
{
pair.FirstStudent = null;
pair.SecondStudent = current.Value.EventArgs.Student;
pair.IntervalBetweenJoining = current.Interval;
pair.School = current.Value.EventArgs.School;
return pair;
}
if (current.Interval <= timeSpan)
{
pair.FirstStudent = previousPair.SecondStudent;
pair.SecondStudent = current.Value.EventArgs.Student;
pair.IntervalBetweenJoining = current.Interval;
pair.School = current.Value.EventArgs.School;
return pair;
}
else
{
return default(StudentPair);
}
})
.Where(p => (p != default(StudentPair)) && (p.FirstStudent != null));
var subscription = observable.Subscribe(StudentPairValueHandler);
school.FillWithStudents(4, TimeSpan.FromSeconds(1));
school.FillWithStudents(2, TimeSpan.FromSeconds(10));
school.FillWithStudents(3, TimeSpan.FromSeconds(2));
school.FillWithStudents(2, TimeSpan.FromSeconds(5));
school.FillWithStudents(5, TimeSpan.FromSeconds(0.6));
Console.WriteLine("Press any key to exit the program");
Console.ReadKey();
subscription.Dispose();
}
static void StudentPairValueHandler(StudentPair pair)
{
if (pair != null && pair.FirstStudent != null)
{
Console.WriteLine($"{pair.SecondStudent.Name} joined {pair.School.Name} {Math.Round(pair.IntervalBetweenJoining.TotalSeconds, 2)} seconds after {pair.FirstStudent.Name}.");
}
}
...
public class StudentPair
{
public Student FirstStudent;
public Student SecondStudent;
public School School;
public TimeSpan IntervalBetweenJoining;
}
public static class Extensions
{
public static void FillWithStudents(this School school, int howMany)
{
FillWithStudents(school, howMany, TimeSpan.Zero);
}
public static void FillWithStudents(this School school, int howMany, TimeSpan gapBetweenEachAdmission)
{
if (school == null)
throw new ArgumentNullException("school");
if (howMany < 0)
throw new ArgumentOutOfRangeException("howMany");
if (howMany == 1)
{
school.AdmitStudent(Student.CreateRandom());
return;
}
for (int i = 0; i < howMany; i++)
{
Thread.Sleep((int)gapBetweenEachAdmission.TotalMilliseconds);
school.AdmitStudent(Student.CreateRandom());
}
}
public async static void FillWithStudentsAsync(this School school, int howMany, TimeSpan gapBetweenEachAdmission)
{
if (school == null)
throw new ArgumentNullException("school");
if (howMany < 0)
throw new ArgumentOutOfRangeException("howMany");
if (howMany == 1)
{
school.AdmitStudent(Student.CreateRandom());
return;
}
for (int i = 0; i < howMany; i++)
{
await Task.Delay(gapBetweenEachAdmission);
school.AdmitStudent(Student.CreateRandom());
}
}
}
static void ObserveStudentsJoiningWithin(TimeSpan TimeSpan)
{
var学校=新学校(“学校1”);
可观察的风险值=
可观察。从事件模式(学校,“学生入学”);
var可观测=可观测的容许。时间间隔()
.Scan(空,(上一对,当前)=>
{
Print(string.Format($“Student在{current.Interval.TotalSeconds}秒之后加入,timeSpan={timeSpan.TotalSeconds}秒”);
var pair=新的StudentPair();
if(previousPair==null)
{
pair.firstststudent=null;
pair.SecondStudent=current.Value.EventArgs.Student;
pair.IntervalBetweenJoining=当前.Interval;
pair.School=current.Value.EventArgs.School;
返回对;
}
if(current.Interval(p!=default(StudentPair))&&(p.firstststudent!=null));
var subscription=observable.subscripte(StudentPairValueHandler);
学校。填充学生(4,时间跨度从秒(1));
学校。填充学生(2,时间跨度从秒(10));
学校。填充学生(3,时间跨度。从秒(2));
学校。填充学生(2,时间跨度从秒(5));
学校。填充学生(5,时间跨度从秒(0.6));
Console.WriteLine(“按任意键退出程序”);
Console.ReadKey();
subscription.Dispose();
}
静态无效StudentPairValueHandler(StudentPair)
{
if(pair!=null&&pair.firstststudent!=null)
{
WriteLine($“{pair.SecondStudent.Name}在{pair.firstststudent.Name}之后加入{pair.School.Name}{Math.Round(pair.intervalbetweenjoin.TotalSeconds,2)}秒);
}
}
...
公共班级学生对
{
公立学生第一名;
公立学校学生;
公立学校;
连接之间的公共时间间隔;
}
公共静态类扩展
{
公立学校和学生(这所学校,有多少人)
{
填充学生(学校、数量、时间跨度为零);
}
公共静态空白填充学生(此学校,int多少,每个任务之间的时间间隔)
{
如果(学校==null)
抛出新的异常(“学校”);
如果(有多少个<0)
抛出新ArgumentOutOfRangeException(“多少”);
如果(数量==1)
{
school.AdmitStudent(Student.CreateRandom());
返回;
}
for(int i=0;i<多少;i++)
{
Sleep((int)间隙介于eachadmission.total毫秒之间);
school.AdmitStudent(Student.CreateRandom());
}
}
公共异步静态void FillWithStudentsAsync(此学校,整数,每个任务之间的时间间隔)
{
如果(学校==null)
抛出新的异常(“学校”);
如果(有多少个<0)
抛出新ArgumentOutOfRangeException(“多少”);
如果(数量==1)
{
school.AdmitStudent(Student.CreateRandom());
返回;
}
for(int i=0;i<多少;i++)
{
等待任务。延迟(每个任务之间的间隙);
school.AdmitStudent(Student.CreateRandom());
}
}
}
你能试试这个,看看它是否能满足你的需要吗
var admissionObservable = Observable
.FromEventPattern<StudentAdmittedEventArgs>(school, "StudentAdmitted")
.Timestamp()
.Buffer(2)
.Where(pair => pair[1].Timestamp - pair[0].Timestamp <= timeSpan)
.Select(pair => new JoiningData
{
Students = Tuple.Create(pair[0].Value.EventArgs.Student, pair[1].Value.EventArgs.Student),
School = pair[0].Value.EventArgs.School,
Interval = pair[1].Timestamp - pair[0].Timestamp
});
IObservable<EventPattern<StudentAdmittedEventArgs>[]> observable =
admissionObservable
.Publish(pxs =>
pxs
.Window(pxs, x => Observable.Timer(timeSpan))
.Select(ys => ys.Take(2)))
.SelectMany(ys => ys.ToArray())
.Where(ys => ys.Skip(1).Any());
i可观察=
可观察到的承认
.Publish(pxs=>
pxs
.Window(pxs,x=>Observable.Timer(timeSpan))
.Select(ys=>ys.Take(2)))
.SelectMany(ys=>ys.ToArray())
其中(ys=>ys.Skip(1.Any());
允许你返回累加器类型。我的错。你是对的。如果你把它作为一个答案写下来?真的很漂亮。非常感谢。我已经用扫描
实现了它,很快就会发布它。关于If
条件,你是对的。我不得不更改它,因为它是错误的。但这是一个非常有趣的会议方法。因为在使用Scan
完成我的解决方案之前,我实际上想知道我是否应该记录DateTime
一名学生在accepted
事件中被录取,并将该信息与EventArgs
一起发送。事实证明,我可以不使用Scan
来记录这些信息,但是这样做了