c# - 使用 LINQ 高效配对时间相关记录

标签 c# database linq temporal pairing

考虑一个项目可以临时配对的数据集。

例如,使用徽章登录和退出某个区域时,可能会记录如下数据:

┏━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┓
┃ Time     ┃ BadgeId ┃ Direction ┃
┣══════════╪═════════╪═══════════┫
┃ 1001930  ┃ A       ┃ IN        ┃
┣━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━┫
┃ 1004901  ┃ B       ┃ IN        ┃
┣━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━┫
┃ 1005192  ┃ A       ┃ OUT       ┃
┣━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━┫
┃ 1012933  ┃ A       ┃ IN        ┃
┣━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━┫
┃ 1014495  ┃ B       ┃ OUT       ┃
┣━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━┫
┃ 1017891  ┃ A       ┃ OUT       ┃
┗━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━━━┛

然后将其暂时配对以获得类似以下内容:

┏━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┓
┃ BadgeId ┃ TimeIn   ┃ TimeOut  ┃
┣═════════╪══════════╪══════════┫
┃ A       ┃ 1001930  ┃ 1005192  ┃
┣━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━┫
┃ A       ┃ 1012933  ┃ 1017891  ┃
┣━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━┫
┃ B       ┃ 1004901  ┃ 1014495  ┃
┗━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━┛

给定一个包含数亿条此类记录的数据集,进行此类时间配对的最有效方法是什么?我对理论上的最佳方法以及使用 LINQ(或其他基于集合的查询语言)的最实际有效的方法感兴趣。

最佳答案

也许这不是处理数百万条记录的最佳理论方法。不过,这是有效的,可以作为进一步改进的起点。

class Program
{
    static void Main(string[] args)
    {
        var StartingRecords = new List<Record>()
        {
            new Record(1001930, "A", "IN"),
            new Record(1004901, "B", "IN"),
            new Record(1005192, "A", "OUT"),
            new Record(1012933, "A", "IN"),
            new Record(1014495, "B", "OUT"),
            new Record(1017891, "A", "OUT"),
        };

        var records = StartingRecords.OrderBy(x => x.BadgeId).ThenBy(x => x.Time).ToList();

        var pairs = records.Skip(1).Zip(records, (second, first) => Tuple.Create(first, second)).
        Where(x => x.Item1.BadgeId == x.Item2.BadgeId &&
        x.Item1.Direction == "IN" && x.Item2.Direction == "OUT").
        Select(x => new Pair(x.Item1.BadgeId, x.Item1.Time, x.Item2.Time)).ToList();

        foreach (var pair in pairs)
            Console.WriteLine(pair.BadgeId + "\t" + pair.TimeIn + "\t" + pair.TimeOut);

        Console.Read();
    }
}

class Record
{
    public long Time { get; set; }
    public string BadgeId { get; set; }
    public string Direction { get; set; }

    public Record(long time, string badgeId, string direction)
    {
        Time = time;
        BadgeId = badgeId;
        Direction = direction;
    }
}

class Pair
{
    public string BadgeId { get; set; }
    public long TimeIn { get; set; }
    public long TimeOut { get; set; }

    public Pair(string badgeId, long timeIn, long timeOut)
    {
        BadgeId = badgeId;
        TimeIn = timeIn;
        TimeOut = timeOut;
    }
}

输出: 1001930 1005192 1012933 1017891 B 1004901 1014495

关于c# - 使用 LINQ 高效配对时间相关记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51155103/

相关文章:

c# - 如何拆分字符串以获得文件名?

mysql - 删除特定用户的 information_schema 表权限

c# - C#中的NHibernate不同数据库备份

c# - 如何为此进行 LINQ 查询?

C# 根据多个条件过滤列表中的项目

c# - Entity Framework Where 子句奇怪的行为

c# - 创建具有动态操作参数的方法

c# - 如何优化 linq 中将 ~4000 行转换到对象的 "select all"语句?

c# - MonoTouch 中自定义 TabBarController 中的 ViewDidLoad 中的公共(public)属性始终为 null

mysql - 如何使自定义 CMS 支持多用户