【问题标题】:C# Read text file content and split it alphabeticallyC#读取文本文件内容并按字母顺序拆分
【发布时间】:2013-12-10 16:02:28
【问题描述】:

我正在尝试编写议程。为每个联系人显示一个小表单(这在 MDI 父表单中)。使用我当前的代码,所有联系人都被写入文件;我呈现信息的方式是一次显示所有联系人(这肯定不会吸引最终用户)。

我当然需要按字母顺序显示联系人。文件每一行的第一个字段是联系人姓氏,可以帮助我进行排序。这个菜鸟卡住的地方是,如何根据姓氏的第一个字母提取行,以便我可以像在真实议程中一样呈现信息?

我看到其他人的一个问题,答案是子列表和“分组依据”功能。但是没有解释代码,那对我来说就像中文一样。

我在想也许可以根据姓氏的第一个字母将我的“所有联系人文件”拆分为小文件(但这会是太多的小文件,也许不是一个好习惯?)。如果这不是一个坏主意,怎么可能实现?

我创建了一个“人”类。并使用此代码添加一个新联系人:

private void btn_CM_addNew_Click(object sender, EventArgs e)
{
    _contact.FirstName = txt_CM_name.Text;
    _contact.LastName = txt_CM_lastName.Text;
    //Person.lista.Add(_contact);
    StreamWriter file = new StreamWriter("C:\\CA_Contacs.txt", true);
    file.WriteLine(_contact.ToString());
    file.Close();
    this.Close();
}

使用此代码,我可以显示“联系人卡片”:

if ((new FileInfo("C:\\CA_Contacs.txt").Exists == true))
{
    var reader = new StreamReader(File.OpenRead("C:\\CA_Contacs.txt"));
    while (!reader.EndOfStream)
    {
        Person _contact = new Person();
        var line = reader.ReadLine();
        var attributes = line.Split(',');
        _contact.LastName = attributes[0]; 
        _contact.FirstName = attributes[1];

        ContactCard contactCardItem = new ContactCard();
        contactCardItem.MdiParent = this;
        contactCardItem.Text = _contact.LastName + ", " + _contact.FirstName;
        contactCardItem.Contact = _contact;
        contactCardItem.Show();
        this.LayoutMdi(MdiLayout.TileVertical);
    }
} 

您会建议哪些方法可以按字母顺序显示联系人?

换句话说,如何从文件中提取以“A”或“a”开头的所有行,将所有这些行放在自己的组中(列表、子列表、文件、您建议的其他结构)所以我以后可以只显示该组,而不是“CA_Contacs.txt”文件中的所有联系人?

【问题讨论】:

    标签: c# list class file-io


    【解决方案1】:

    看看 LINQ,它对这类事情非常强大。我建议您不仅要复制和粘贴,还要实际了解这些行的含义。

    这行代码将为您提供您所需要的:

    var contacts = from contact in (from ele in File.ReadAllLines(@"C:\\your.file")
                     // local variable with the splitted name
                     let name = line.Split(',') 
                     // Get a new Person-object
                     select new Person(){ LastName = name[0], FirstName = name[1] })
                   // Group the Person-objects by the first letter of their last name
                   group contact by contact.LastName.First() into g
                   // Order them by their "key", ie A, B, C instead of random order.
                   order by g.Key
                   // Return the grouping we have created
                   select g;
    

    你可以这样使用它:

    foreach (var contactGroup in contacts) {
      var header = contactGroup.Key; // ie 'A', 'B' etc
      // do something with header
      foreach (var contact in contactGroup)
      {
        // do something with contact (a Person-type instance)
      }
    }
    

    【讨论】:

    • 感谢您的详细解释。我将首先了解您提出的代码的作用,然后将其集成到我的项目中:)
    • 嗨,菜鸟问题:密钥是如何定义的?
    • @DMS 这一行:group contact by contact.LastName.First() into g 将所有联系人分组到由contact.LastName.First()(即键)定义的组中,这有意义吗?
    • 谢谢,我想我现在看到了:“by contact.LastName.First()” ... 表示查看contact.LastName 中的第一个字符
    【解决方案2】:

    当循环并读取文本文件的行时,不要立即创建“联系人卡片”,而是构建某种类型的通用集合(列表、字典等)。该对象将为您提供强大的方法,例如 .Sort()。

    在您的 Collection 对象构建和排序后,循环并创建您的“ContactCard”。

    这里是stackoverflow 的集合类型详解:

    Where can I learn about the various types of .NET lists?

    【讨论】:

    • 谢谢 Bo TX,我会试试看的。
    【解决方案3】:

    除了博TX'的回答:

    构建集合后,您可以使用 Linq 对其进行查询,例如。问。

    using System.Linq;
    .....
    
    
    IEnumerable<ContactCard> contacts = ...;
    

    => 对象构建/填充(见上文)

    IEnumerable<ContactCard> contactsWithA = contacts.Where(cc => cc.LastName.ToLower().StartsWith("a"));
    

    【讨论】:

    • 谢谢macrobbsen,这肯定有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    相关资源
    最近更新 更多