将两个对象与linq组合的更好方法是什么?

时间:2013-07-30 20:47:59

标签: c# linq

我们的一些数据并不是最干净的。例如,如果一个人以两种不同的方式给出了他们的地址,他可能会在输出中出现两次:一次用" 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查询来获取它。

此外,上述查询中唯一相关的信息是日期,因为我已在先前的查询中分离出不同的帐户。由于那个很好,我没想到把它包括在这里是值得的。

6 个答案:

答案 0 :(得分:3)

不是使用痛苦的写入查询,而是更好地浏览数据库并合并重复的记录?如果你这样做,你的查询会看起来更好。

答案 1 :(得分: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字段。

答案 2 :(得分: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)))

答案 3 :(得分:0)

如果您无法更改数据结构,那么

之类的内容如何
var records = report.GroupBy(r => r.Date)
    .Select(n => new MilkBottleRecord(report.First, n.Sum(x => x.Bottles)));

和构造函数

MilkBottleReport(MilkBottleReport original, int newBottles); 

答案 4 :(得分:0)

作为您问题的答案 - 创建一个copy constructor,您的LINQ看起来更好 但正如archer884所说,LINQ可能会窒息;而且我补充说,做一大块数据而无法知道进度是不好的 - 按记录迭代记录 另外:正如zmbq所说 - 将数据清理移动到它自己的模块/ dll /汇编/机器/流程/业务。

答案 5 :(得分:0)

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

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

LINQ并不是万灵药,虽然您可能会使用LINQ提出一个通用的规范化查询,但我不想让您支持并维护它。还有其他工具可用于将真实数据清理成计算机可以匹配的内容。