C#使用LINQ读取和汇总文本文件

时间:2012-06-04 01:26:58

标签: c# linq text

我已经为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,但我无法让它们正常工作。如何将所有这些函数包装到一个查询中?

编辑:我想我的问题是错误的。我并不是说我必须在一个查询中完成所有操作...我想在一个查询中用一个清晰​​,简洁,高效的方法来解决这个问题 IS THERE 吗?如果不是,我会回到循环中去。

如果我能指出正确的方向,那将是一个巨大的帮助。 如果有人想要做到这一点有一个更容易的想法,请告诉我。

我只是想避免遍历大量的值并在每一行使用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()      
            };

3 个答案:

答案 0 :(得分:3)

使用File.ReadAllLines的缺点是在操作之前必须将整个文件拉入内存。另外,使用Columns []有点笨拙。您可能希望将我的article describing using DynamicObject and streaming文件视为替代实现。分组/计数操作是该讨论的次要部分。

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

            }

        }

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

结果截屏

enter image description here

修改

这是一个提供相同输出的大查询

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();