将分隔转换为固定宽度的最佳方法

时间:2010-04-16 16:25:03

标签: c# linq

转换此内容的最佳方式是什么:

FirstName,LastName,Title,BirthDate,HireDate,City,Region
Nancy,Davolio,Sales Representative,1948-12-08,1992-05-01,Seattle,WA
Andrew,Fuller,Vice President Sales,1952-02-19,1992-08-14,Tacoma,WA
Janet,Leverling,Sales Representative,1963-08-30,1992-04-01,Kirkland,WA
Margaret,Peacock,Sales Representative,1937-09-19,1993-05-03,Redmond,WA
Steven,Buchanan,Sales Manager,1955-03-04,1993-10-17,London,NULL
Michael,Suyama,Sales Representative,1963-07-02,1993-10-17,London,NULL
Robert,King,Sales Representative,1960-05-29,1994-01-02,London,NULL
Laura,Callahan,Inside Sales Coordinator,1958-01-09,1994-03-05,Seattle,WA
Anne,Dodsworth,Sales Representative,1966-01-27,1994-11-15,London,NULL

到此:

FirstName  LastName             Title                          BirthDate   HireDate   City            Region
---------- -------------------- ------------------------------ ----------- ---------- --------------- ---------------
Nancy      Davolio              Sales Representative           1948-12-08  1992-05-01  Seattle         WA
Andrew     Fuller               Vice President, Sales          1952-02-19  1992-08-14  Tacoma          WA
Janet      Leverling            Sales Representative           1963-08-30  1992-04-01  Kirkland        WA
Margaret   Peacock              Sales Representative           1937-09-19  1993-05-03  Redmond         WA
Steven     Buchanan             Sales Manager                  1955-03-04  1993-10-17  London          NULL
Michael    Suyama               Sales Representative           1963-07-02  1993-10-17  London          NULL
Robert     King                 Sales Representative           1960-05-29  1994-01-02  London          NULL
Laura      Callahan             Inside Sales Coordinator       1958-01-09  1994-03-05  Seattle         WA
Anne       Dodsworth            Sales Representative           1966-01-27  1994-11-15  London          NULL

6 个答案:

答案 0 :(得分:3)

我创建了一个自定义类来保存信息,然后为CSV文件中的每一行执行循环,在逗号上拆分并填充自定义对象。然后将它们全部放入列表或IEnumrable中并将其抛入转发器/ datagrid。

public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Title { get; set; }
        public DateTime BirthDate { get; set; }
        public DateTime HireDate { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
    }

    public void Parse(string csv)
    {
        string[] lines = csv.Split( Environment.NewLine.ToCharArray() );
                    List<Person> persons = new List<Person>();

        foreach (string line in lines)
        {
            string[] values = line.Split( ',' );

            Person p = new Person();

            p.FirstName = values[ 0 ];
            p.LastName = values[ 1 ];

                            persons.Add( p );
            //.... etc etc
        }
    }

答案 1 :(得分:3)

这符合您所述的要求,并使用LINQ(因为您的问题被标记为LINQ),但不一定最佳

class Program
{
    static void Main(string[] args)
    {
        List<string> inputs = new List<string>
        {
            "FirstName,LastName,Title,BirthDate,HireDate,City,Region",
            "Nancy,Davolio,Sales Representative,1948-12-08,1992-05-01,Seattle,WA",
            "Andrew,Fuller,Vice President Sales,1952-02-19,1992-08-14,Tacoma,WA",
            "Janet,Leverling,Sales Representative,1963-08-30,1992-04-01,Kirkland,WA",
            "Margaret,Peacock,Sales Representative,1937-09-19,1993-05-03,Redmond,WA",
            "Steven,Buchanan,Sales Manager,1955-03-04,1993-10-17,London,NULL",
            "Michael,Suyama,Sales Representative,1963-07-02,1993-10-17,London,NULL",
            "Robert,King,Sales Representative,1960-05-29,1994-01-02,London,NULL",
            "Laura,Callahan,Inside Sales Coordinator,1958-01-09,1994-03-05,Seattle,WA",
            "Anne,Dodsworth,Sales Representative,1966-01-27,1994-11-15,London,NULL"
        };

        // TODO: These widths would presumably be configurable
        List<int> widths = new List<int> { 12, 22, 32, 13, 12, 17, 8 };

        List<string> outputs = inputs.Select(s => ToFixedWidths(s, ',', widths)).ToList();

        outputs.ForEach(s => System.Diagnostics.Debug.WriteLine(s));

        Console.ReadLine();
    }

    private static string ToFixedWidths(string s, char separator, List<int> widths)
    {
        List<string> split = s.Split(separator).ToList();

        // TODO: Error handling - what if there are more/less separators in
        // string s than we have width values?

        return string.Join(String.Empty, split.Select((ss, i) => ss.PadRight(widths[i], ' ')).ToArray());
    }
}

在生产场景中虽然我希望看到这些数据被读入适当的Person类,正如Matt在他的回答中所推荐的那样。

答案 2 :(得分:2)

我知道这样做最简单的方法是 PowerShell

PS >  Import-Csv .\x.csv | Format-Table -AutoSize

FirstName LastName Title BirthDate HireDate City Region --------- -------- ----- --------- -------- ---- ------ Nancy Davolio Sales Representative 1948-12-08 1992-05-01 Seattle WA Andrew Fuller Vice President Sales 1952-02-19 1992-08-14 Tacoma WA Janet Leverling Sales Representative 1963-08-30 1992-04-01 Kirkland WA ...

答案 3 :(得分:1)

这里有两个问题。单独考虑它们,您将更容易找到一个好的解决方案。

  1. 将CSV格式的输入数据解析为有用的格式。

  2. 以某种方式展示您的数据

  3. 不要编写自己的CSV解析器。规则有点棘手,但格式众所周知。从长远来看,做错了会很糟糕。您可以调用.NET框架中的现有CSV库,但我对它们知之甚少。但是,此问题非常适合C#中的新dynamic功能。这是一个看起来很有希望的人:http://tonikielo.blogspot.com/2010/01/c-40-dynamic-linq-to-csvhe.html

    我假设打印数据是一个微不足道的问题,你不需要我们的帮助。如果没有,您需要提供更多信息,例如您希望如何决定列的宽度。

答案 4 :(得分:0)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace StringParsingWithLinq
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var inputs = new List<string>
                             {
                                 "FirstName,LastName,Title,BirthDate,HireDate,City,Region",
                                 "Nancy,Davolio,Sales Representative,1948-12-08,1992-05-01,Seattle,WA",
                                 "Andrew,Fuller,\"Vice President, Sales\",1952-02-19,1992-08-14,Tacoma,WA",
                                 "Janet,Leverling,Sales Representative,1963-08-30,1992-04-01,Kirkland,WA",
                                 "Margaret,Peacock,Sales Representative,1937-09-19,1993-05-03,Redmond,WA",
                                 "Steven,Buchanan,Sales Manager,1955-03-04,1993-10-17,London,NULL",
                                 "Michael,Suyama,Sales Representative,1963-07-02,1993-10-17,London,NULL",
                                 "Robert,King,Sales Representative,1960-05-29,1994-01-02,London,NULL",
                                 "Laura,Callahan,Inside Sales Coordinator,1958-01-09,1994-03-05,Seattle,WA",
                                 "Anne,Dodsworth,Sales Representative,1966-01-27,1994-11-15,London,NULL"
                             };

            Console.Write(FixedWidthHelper.ReadLines(inputs)
                              .ToFixedLengthString());
            Console.ReadLine();
        }

        #region Nested type: FixedWidthHelper

        public class FixedWidthHelper
        {
            private readonly Regex _csvRegex = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
            private readonly List<string[]> _data = new List<string[]>();
            private List<int> _fieldLen;

            public static FixedWidthHelper ReadLines(List<string> lines)
            {
                var fw = new FixedWidthHelper();
                lines.ForEach(fw.AddDelimitedLine);
                return fw;
            }

            private void AddDelimitedLine(string line)
            {
                string[] fields = _csvRegex.Split(line);

                if (_fieldLen == null)
                    _fieldLen = new List<int>(fields.Select(f => f.Length));

                for (int i = 0; i < fields.Length; i++)
                {
                    if (fields[i].Length > _fieldLen[i])
                        _fieldLen[i] = fields[i].Length;
                }

                _data.Add(fields);
            }

            public string ToFixedLengthString()
            {
                var sb = new StringBuilder();
                foreach (var list in _data)
                {
                    for (int i = 0; i < list.Length; i++)
                    {
                        sb.Append(list[i].PadRight(_fieldLen[i] + 1, ' '));
                    }
                    sb.AppendLine();
                }

                return sb.ToString();
            }
        }

        #endregion
    }
}

alt text

答案 5 :(得分:0)

为了这个目的,我刚写了tablify。使用

安装
[sudo -H] pip3 install tablify

tablify input.dat

会给你

FirstName , LastName  , Title                    , BirthDate  , HireDate   , City     , Region
Nancy     , Davolio   , Sales Representative     , 1948-12-08 , 1992-05-01 , Seattle  , WA
Andrew    , Fuller    , Vice President Sales     , 1952-02-19 , 1992-08-14 , Tacoma   , WA
Janet     , Leverling , Sales Representative     , 1963-08-30 , 1992-04-01 , Kirkland , WA
Margaret  , Peacock   , Sales Representative     , 1937-09-19 , 1993-05-03 , Redmond  , WA
Steven    , Buchanan  , Sales Manager            , 1955-03-04 , 1993-10-17 , London   , NULL
Michael   , Suyama    , Sales Representative     , 1963-07-02 , 1993-10-17 , London   , NULL
Robert    , King      , Sales Representative     , 1960-05-29 , 1994-01-02 , London   , NULL
Laura     , Callahan  , Inside Sales Coordinator , 1958-01-09 , 1994-03-05 , Seattle  , WA
Anne      , Dodsworth , Sales Representative     , 1966-01-27 , 1994-11-15 , London   , NULL

从那里开始,应该很容易根据您的需要调整文件。