【问题标题】:Linq - difference with previous element [closed]Linq - 与前一个元素的区别[关闭]
【发布时间】:2014-03-14 21:12:50
【问题描述】:

有没有办法根据数据元素之间的差异对数据元素进行分组?

List<Message> messages = new List<Message>(); 

class Message
{
    private DateTime Date { get; set; }
    private string Text { get; set; }
}

消息日期中的示例数据:

14.3 2014 20:28:15
14.3 2014 20:32:17
14.3 2014 20:37:25
14.3 2014 22:38:43
14.3 2014 20:40:23
14.3 2014 20:42:07
14.3 2014 20:43:54
14.3 2014 20:52:26
14.3 2014 20:53:41
14.3 2014 20:55:37
14.3 2014 20:58:44

我需要像这样的LINQ 查询该组。如果没有记录六分钟,将开始一个新的组。

Group 1
    14.3 2014 20:28:15
    14.3 2014 20:32:17

Group 2
    14.3 2014 20:37:25
    14.3 2014 20:38:43
    14.3 2014 20:40:23
    14.3 2014 20:42:07
    14.3 2014 20:43:54

Group 3
    14.3 2014 20:52:26
    14.3 2014 20:53:41
    14.3 2014 20:55:37
    14.3 2014 20:58:44

【问题讨论】:

  • 在不知道你的类名、属性名等的情况下编写一个示范性的 linq 查询真的很难。你能发布实际的类信息,并展示你迄今为止为解决问题所做的尝试吗?
  • 我编辑问题。感谢您的关注,谢谢您
  • @Lenny 20:32:1720:37:25 之间的时间不到 6 分钟。为什么他们不在同一个组?

标签: c# .net linq


【解决方案1】:

当然,我们可以创建自己的GroupWhile 方法,让我们在满足条件时对项目进行分组:

var query = messages.GroupWhile((prev, current) => 
    prev.Date.AddMinutes(6) >= current.Date));

GroupWhile 可以这样实现:

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
    this IEnumerable<T> source, Func<T, T, bool> predicate)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;

        List<T> list = new List<T>() { iterator.Current };

        T previous = iterator.Current;

        while (iterator.MoveNext())
        {
            if (!predicate(previous, iterator.Current))
            {
                yield return list;
                list = new List<T>();
            }

            list.Add(iterator.Current);
            previous = iterator.Current;
        }
        yield return list;
    }
}

【讨论】:

  • 它遵循问题的描述,但产生不同的结果(只有 2 组)。可能是因为文本描述和OP设置的预期输出不匹配......
【解决方案2】:

如果您只想使用本机 Linq 方法执行此操作,则必须在 linq 查询之外保留一种状态变量。这不是一个好的做法,但这会起作用:

var groupNum = 0;
var prevDate = DateTime.MinValue;
var threshold = -TimeSpan.FromMinutes(6); // negative time makes things easier

var groups = messages.GroupBy(
    m => prevDate - (prevDate = m.Date) < threshold ? ++groupNum : groupNum);

同样,我们并不推荐在 Linq 查询之外跟踪状态变量,而且这种代码非常丑陋和令人困惑。但它有效。

我可能会在生产环境中使用更像 Servy's answer 的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-24
    • 2013-03-21
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 2013-01-22
    相关资源
    最近更新 更多