【问题标题】:ICal.net Calendar ComparisonICal.net 日历比较
【发布时间】:2017-11-08 08:30:26
【问题描述】:

我一直在使用一个名为 ICal.net 的 nuget 包来加载 ics 文件以检查最近添加的事件。

我注意到,在为此使用 IEnumerable Except 方法时,即使您可以看到添加了更多事件,也会错过一些事件。

我在 Event 中发现了 Uid 属性,检查了它并注意到它是独一无二的 - https://github.com/rianjs/ical.net/blob/5176d27ac243eb98a01157f2ed7ff3e2852b98eb/v2/ical.NET/Interfaces/Components/IUniqueComponent.cs#L14

我为此使用 Uid 写了一个IEqualityComparer<IEvent>,但现在所有事件都被视为新事件。

只是想知道是否有人对我如何获取 2 个日历、比较事件并找出差异有任何建议?目前有 2000 多个事件,并且还在不断增加,因此努力保持其性能。

【问题讨论】:

标签: c# comparison ienumerable ical-dotnet


【解决方案1】:

如果我理解正确,您有两个日历集合。一个代表具有多个 VEVENT 的 VCALENDAR,第二个代表稍后某个时间点的相同 VCALENDAR + VEVENT。出于显而易见的原因,通常后期的 VCALENDAR 比早期的日历有更多的事件。并且您想比较两者以查看差异,即找到新事件。

  • 使用Uid 可能就足够了,也可能不够;这取决于您的日历系统。虽然每个 UID 应该是唯一的,但这取决于您的应用程序来保证。当 ical.net 创建事件时,它会执行 Guid.NewGuid().ToString(),因此如果您使用 ical.net 创建事件,它们应该是唯一的。 Google 日历和(我认为)其他流行的日历应用程序也提供确定性唯一的 Uid。
  • ical.net 不认为 Uid 对相等或散列的目的很重要。相反,它关注事件本身的构成。

如果您知道每个事件的 UID 是唯一的,并且您对比较两个具有不匹配 UID 的事件没有兴趣,我会这样做:

var eventIdSet = new HashSet<string>(StringComparison.OrdinalIgnoreCase);
var firstEventIds = firstCalendarCollection
    .SelectMany(cc => cc.Event)
    .Select(e => e.Uid);
eventIdSet.UnionWith(firstEventIds);

var secondEventIds = secondCalendarCollection
    .SelectMany(cc => cc.Event)
    .Select(e => e.Uid);

eventIdSet.ExceptWith(secondEventIds);

这应该会为您提供第一个集合中存在的新日历 ID,而不是第二个集合。

如果您想比较事件内容,我会遵循相同的模式,在 Event 对象处停止:

var firstSet = new HashSet<Event>();
var firstEvents = firstCalendarCollection.SelectMany(cc => cc.Event);
firstSet.UnionWith(firstEventIds);

var secondEvents = secondCalendarCollection.SelectMany(cc => cc.Event);
firstSet.ExceptWith(secondEvents);

这将做同样的事情,但正如我上面所说,事件 ID 被内部 GetHashCodeEquals 实现忽略。

单独比较Uids 比比较每个Event 的全部内容要快。也就是说,除非这是一个繁忙的服务器应用程序,必须每秒多次执行此操作,否则这无关紧要。我们正在使用 ical.net,并使用 800-1000 个日历事件进行这样的设置操作,它是 WPF 应用程序中计算时间的毫秒数。除非在极端情况下,否则您可能不会注意到 Uid 比较和整个 Event 内容比较之间的区别。

编辑:我创建了一个 wiki 页面:https://github.com/rianjs/ical.net/wiki/Comparing-collections-of-calendar-events

【讨论】:

  • 我正面临 ical.net 的问题。使用 ical.net 在我的 .Net 应用程序中创建日历 ics。但是,在我的环境中,日历电子邮件看起来不错,可以接受或拒绝。然而,在客户环境中,没有接受或取消此请求的选项。这只发生在 Outlook 2010 和 Outlook 2016 的客户身上。但是,在我们的环境中,我们在 Outlook 2010 和 2016 上看到日历电子邮件很好。任何帮助将不胜感激!谢谢
【解决方案2】:

我建议使用 LINQ 进行 Where In 查询。

假设您有两个集合(已注册和可能是新的):

List<string> registeredIds = GetRegisteredComponentsUIds();

List<ComponentImplemenation> newEvents = GetNewEvents();

List<ComponentImplemenation> result = newEvents.Where(m => registeredIds.Contains(m.Uid))
                                               .ToList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 2018-02-03
    • 2021-06-04
    相关资源
    最近更新 更多