1

我已经阅读了许多针对 LINQ 的单独功能的不同解决方案,这些解决方案放在一起可以解决我的问题。我的问题是我仍在努力思考如何正确地将 LINQ 语句组合在一起。我似乎无法正确使用语法,或者它出现了混杂的信息,而不是我想要的。

如果其中一半看起来像重复,我提前道歉。我的问题比仅仅阅读文件更具体。我希望这一切都在同一个查询中。

不过说到点子上了。。

我正在阅读带有分号分隔的数据列的文本文件。

一个例子是:

US;Fort Worth;TX;Tarrant;76101
US;Fort Worth;TX;Tarrant;76103
US;Fort Worth;TX;Tarrant;76105
US;Burleson;TX;Tarrant;76097
US;Newark;TX;Tarrant;76071
US;Fort Worth;TX;Tarrant;76103
US;Fort Worth;TX;Tarrant;76105

这是我到目前为止所拥有的:

var items = (from c in (from line in File.ReadAllLines(myFile)
    let columns = line.Split(';')
    where columns[0] == "US"
    select new
    {
        City = columns[1].Trim(),
        State = columns[2].Trim(),
        County = columns[3].Trim(),
        ZipCode = columns[4].Trim()
    })
    select c);

这适用于读取文件。但在那之后我的问题是我不想要原始数据。我要一个总结。

具体来说,我需要计算城市、州组合的出现次数以及邮政编码出现的次数。

我最终会用它制作一个树视图。我的目标是让它有点像这样布置:

- Fort Worth,TX (5)
       -  76101 (1)
       -  76103 (2)
       -  76105 (2)  

- Burleson,TX (1)
       - 76097 (1)

- Newark,TX (1)
     - 76071 (1)

我可以晚点做树的事情,因为还有其他处理要做。

所以我的问题是:如何结合查询本身中特定值的计数?我知道 GroupBy 函数,也见过 Aggregates,但我无法让它们正常工作。如何将所有这些函数包装到一个查询中?

编辑:我想我问错了问题。我并不是说我必须在一个查询中完成所有这些操作......我问的是有没有一种清晰、简洁和有效的方法可以在一个查询中使用 LINQ 来做到这一点?如果没有,我将返回循环。

如果我能指出正确的方向,那将是一个巨大的帮助。如果有人有更简单的想法来做这一切,请告诉我。

我只是想避免遍历大量值并在每一行上使用 Regex.Split。

让我知道是否需要澄清。

谢谢!

*编辑 6/15 ***

我想到了。感谢那些回答它的人提供了帮助,但并不是我所需要的。作为旁注,我最终还是把它全部改变了。LINQ 实际上比其他方式慢,因为它不相关,所以我不会进入。至于那些多次评论“一个查询有它很愚蠢”的人,那是设计师的决定。并非所有“最佳实践”都适用于所有地方。它们是指导方针。相信我,我确实想让我的代码清晰易懂,但我也有一个非常具体的理由来这样做。

我非常感谢您的帮助和指导。

下面是我使用但后来放弃的原型。

    /* Inner LINQ query Reads the Text File and gets all the Locations.
     * The outer query summarizes this by getting the sum of the Zips 
     * and orders by City/State then ZIP */


var items = from Location in(
    //Inner Query Start
    (from line in File.ReadAllLines(FilePath)
    let columns = line.Split(';')
    where columns[0] == "US" & !string.IsNullOrEmpty(columns[4])
    select new
    {
    City = (FM.DecodeSLIC(columns[1].Trim()) + " " + columns[2].Trim()),
    County = columns[3].Trim(),
                   ZipCode = columns[4].Trim()
    }
    ))
    //Inner Query End
    orderby Location.City, Location.ZipCode  
                   group Location by new { Location.City, Location.ZipCode , Location.County} into grp
            select new
            {
            City = grp.Key.City,
            County = grp.Key.County,
            ZipCode = grp.Key.ZipCode,
            ZipCount = grp.Count()      
            };
4

3 回答 3

3

使用 File.ReadAllLines 的缺点是您必须在操作之前将整个文件拉入内存。此外,使用 Columns[] 有点笨拙。您可能需要考虑我的文章描述使用 DynamicObject 和流式传输文件作为替代实现。分组/计数操作是次要的讨论。

于 2012-06-15T18:41:47.360 回答
1
        var items = (from c in
                         (from line in File.ReadAllLines(myFile)
                          let columns = line.Split(';')
                          where columns[0] == "US"
                          select new
                                     {
                                         City = columns[1].Trim(),
                                         State = columns[2].Trim(),
                                         County = columns[3].Trim(),
                                         ZipCode = columns[4].Trim()
                                     })
                     select c);
        foreach (var i in items.GroupBy(an => an.City + "," + an.State))
        {
            Console.WriteLine("{0} ({1})",i.Key, i.Count());
            foreach (var j in i.GroupBy(an => an.ZipCode))
            {
                Console.WriteLine(" - {0} ({1})", j.Key, j.Count());

            }

        }
于 2012-06-04T02:08:20.367 回答
1

将所有内容都集中到一个查询中是没有意义的。最好拆分查询以使其有意义。试试这个你的结果

var grouped = items.GroupBy(a => new { a.City, a.State, a.ZipCode }).Select(a => new { City = a.Key.City, State = a.Key.State, ZipCode = a.Key.ZipCode, ZipCount = a.Count()}).ToList();

结果截图

在此处输入图像描述

编辑

这是一个大的长查询,它给出了相同的输出

var itemsGrouped = File.ReadAllLines(myFile).Select(a => a.Split(';')).Where(a => a[0] == "US").Select(a => new { City = a[1].Trim(), State = a[2].Trim(), County = a[3].Trim(), ZipCode = a[4].Trim() }).GroupBy(a => new { a.City, a.State, a.ZipCode }).Select(a => new { City = a.Key.City, State = a.Key.State, ZipCode = a.Key.ZipCode, ZipCount = a.Count() }).ToList();
于 2012-06-04T02:10:04.647 回答