2

我们的一些数据不是最干净的。例如,如果一个人以两种不同的方式给出了他们的地址,他可能会出现在输出中两次:一次是“RD”,另一次是“Road”。

有趣的是,他们一半的数据出现在一条记录中,另一半出现在另一条记录中。所以...

Johnny, Larsen Rd, Tuesday, 4 milk bottles
Johnny, Larsen Road, Tuesday, 3 milk bottles

约翰尼周二的消费量实际上是 7 瓶牛奶。我正在尝试编写一个 LINQ 来合并这两个对象而不会带来太多痛苦,但这就是我到目前为止所拥有的一切:

var records = report.GroupBy(r => r.Date)
    .Select(n => new MilkBottleRecord() {
        Name = report.First().Name,
        Address = report.First().Address,
        Date = report.First().Date,
        Bottles = n.Sum(x => x.Bottles),
    });

有什么建议么?

我应该指出 A) 这不是我们的数据,所以我们不能真正进行清理,并且 B) 我们是通过 CSV 而不是从 SQL 查询中获取它的。

此外,上述查询中唯一相关的信息是日期,因为我已经在之前的查询中分离了不同的帐户。既然那个很好,我认为不值得你花时间把它包括在这里。

4

6 回答 6

3

与其使用编写痛苦的查询,不如遍历数据库并合并重复记录不是更好吗?如果你这样做,你的查询看起来会好很多。

于 2013-07-30T20:51:38.223 回答
1

你可以尝试这样的事情:

IEqualityComparer<MilkBottleRecord> comparer = /* instantiate a comparer */
var records = report.GroupBy(x => x, comparer)
                    .Select(g => new MilkBottleRecord(g.Key) {
                        Bottles = g.Sum(x => x.Bottles))
                    });

基本思想是:外部化你的比较逻辑,创建一个允许你复制显着信息的复制构造函数,然后用 Sum 覆盖 Bottles 字段。

于 2013-07-30T20:54:31.693 回答
0

履行公司使用CASS软件来修复和规范地址。如果你在做专业的事情,你可能会考虑一下。

否则,您可以执行以下操作:

string NormalizeAddress(string str)
{
    // should probably be a bit more intelligent than this, but maybe not.
    str = str.ToUpperInvariant();
    str = str.Replace ("ROAD", "RD");
    return str;
}

var records = report.GroupBy(r =>
                         Tuple.Create(r.Date, NormalizeAddress(r.Address)))
于 2013-07-30T20:53:40.417 回答
0

如果你不能改变数据结构,像

var records = report.GroupBy(r => r.Date)
    .Select(n => new MilkBottleRecord(report.First, n.Sum(x => x.Bottles)));

和一个构造函数

MilkBottleReport(MilkBottleReport original, int newBottles); 
于 2013-07-30T20:57:06.420 回答
0

作为您问题的答案-创建一个复制构造函数,您的 LINQ 看起来更好。
但正如archer884所说,LINQ可能会窒息;我补充说,在不知道进度的情况下处理大量数据是不好的——逐条记录迭代。
另外:正如 zmbq 所指出的 - 将数据清理移动到它自己的模块/dll/程序集/机器/进程/业务。

于 2013-07-30T20:59:25.253 回答
0

真正的答案是清理和规范化您的数据。决定在地址中是否使用拼写或缩写类型的通道(Road/Rd、Avenue/Av/Ave、Street/St、Drive/Dr、Lane/Ln),然后更改您的数据以符合您的标准'已经选择和重复数据删除。

答案的另一部分是使用不可变标识符来区分记录。您很可能最终会遇到两个不同的人,他们名叫“约翰尼”,他们住在“拉森路”上。它甚至可以是同一个拉森路;约翰和绰号约翰尼很常见,以至于很容易有两个约翰经过约翰尼,住在一条特定的拉森路;他们希望通过姓氏、地段或公寓号码来区分,但如果您认为这些数据中的任何一个是可疑的,那么您仍然有问题。解决方案是一个唯一标识符,例如一个帐号,让您能够积极区分两个住在拉森路的名叫约翰尼的不同人,或者反过来识别任何其他“唯一识别信息”中的差异,否则会导致您误认一个人两个。

LINQ 不是万能的,虽然您可能会想出一个使用 LINQ 的通用规范化查询,但我不想落后于您并维护它。还有其他工具可用于将现实世界的数据清理成计算机可以匹配的东西。

于 2013-07-30T21:06:26.030 回答