C#比较csv中不同行的字段

时间:2016-03-31 20:19:06

标签: c# csv textfieldparser

我试图比较一行中数组的0索引和下一行的0索引的值。想象一下CSV,我在第一列中有一个唯一的标识符,第二列中有一个对应的值。

USER1, 1P
USER1, 3G
USER2, 1P
USER3, 1V

我想检查下一行(或前一个,如果更容易)进行比较的[0]的值,如果它们是相同的(如在示例中那样)将它连接到索引1。也就是说,数据应该读作

USER1, 1P, 3G
USER2, 1P
USER3, 1V

在传递给下一个函数之前。到目前为止我已经

 private void csvParse(string path)
        {
            using (TextFieldParser parser = new TextFieldParser(path))
                {
                    parser.Delimiters = new string[] { "," };
                    while (!parser.EndOfData)
                    {
                        string[] parts = parser.ReadFields();
                        if (parts == null)
                        {
                            break;
                        }
                        contact.ContactId = parts[0];
                        long nextLine;
                        nextLine = parser.LineNumber+1;
//if line1 parts[0] == line2 parts[0] etc.
                    }
                }
            }

有没有人有任何建议?谢谢。

4 个答案:

答案 0 :(得分:1)

如何将数组保存到变量中:

private void csvParse(string path)
        {
            using (TextFieldParser parser = new TextFieldParser(path))
                {
                    parser.Delimiters = new string[] { "," };
                    string[] oldParts = new string[] { string.Empty };
                    while (!parser.EndOfData)
                    {
                        string[] parts = parser.ReadFields();
                        if (parts == null || parts.Length < 1)
                        {
                            break;
                        }

                        if (oldParts[0] == parts[0])
                        {
                             // concat logic goes here
                        }
                        else
                        {
                            contact.ContactId = parts[0];
                        }

                        long nextLine;
                        nextLine = parser.LineNumber+1;
                        oldParts = parts;
//if line1 parts[0] == line2 parts[0] etc.
                    }
                }
            }

答案 1 :(得分:1)

如果我理解正确,那么你所问的基本上是“如何根据第一列中的值对第二列中的值进行分组?”。

快速而简洁的方法是SQL

var linesGroupedByUser =
    from line in File.ReadAllLines(path)
    let elements = line.Split(',')
    let user = new {Name = elements[0], Value = elements[1]}
    group  user by user.Name into users
    select users;

foreach (var user in linesGroupedByUser)
{
    string valuesAsString = String.Join(",", user.Select(x => x.Value));

    Console.WriteLine(user.Key + ", " + valuesAsString);
}

我已经省略了TextFieldParser课程的使用,但你可以轻松地使用它。但是,这种方法需要您能够将所有数据加载到内存中。你没有提到这是否可行。

答案 2 :(得分:0)

执行此类操作的最简单方法是将每一行转换为对象。您可以使用CsvHelperhttps://www.nuget.org/packages/CsvHelper/为您完成工作,也可以迭代每一行并解析为一个对象。它是一个很棒的工具,它知道如何正确地将CSV文件解析为对象集合。然后,无论您是自己创建集合还是使用CsvHelper,都可以使用LinqGroupByhttps://msdn.microsoft.com/en-us/library/bb534304(v=vs.100).aspx,您的&#34;密钥&#34; (在本例中为UserId)和Aggregatehttps://msdn.microsoft.com/en-us/library/bb549218(v=vs.110).aspx,将另一个属性转换为字符串。然后,您可以使用新的分组收集作为最终目标(将其写入文件或将其用于您需要的任何内容)。

答案 3 :(得分:0)

您基本上找到了所有唯一条目,因此将它们放入以字母为按键的字典中。如下:

 private void csvParse(string path)
    {
        using (TextFieldParser parser = new TextFieldParser(path))
        {
            parser.Delimiters = new string[] { "," };
            Dictionary<string, List<string>> uniqueContacts = new Dictionary<string, List<string>>();
            while (!parser.EndOfData)
            {
                string[] parts = parser.ReadFields();
                if (parts == null || parts.Count() != 2)
                {
                    break;
                }
                //if contact id not present in dictionary add
                if (!uniqueContacts.ContainsKey(parts[0]))
                    uniqueContacts.Add(parts[0],new List<string>());
                //now there's definitely an existing contact in dic (the one 
                //we've just added or a previously added one) so add to the                   
                //list of strings for that contact
                uniqueContacts[parts[0]].Add(parts[1]);
            }

            //now do something with that dictionary of unique user names and
            // lists of strings, for example dump them to console in the 
            //format you specify:

            foreach (var contactId in uniqueContacts.Keys)
            {

                var sb = new StringBuilder();
                sb.Append($"contactId, ");
                foreach (var bit in uniqueContacts[contactId])
                {
                    sb.Append(bit);
                    if (bit != uniqueContacts[contactId].Last())
                        sb.Append(", ");
                }
                Console.WriteLine(sb);
            }
        }
    }