0

我有一个像这样的人类:

class Person
{
    string Id { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
}

有一个 CSV 文件,其中包含人员数据,例如

"123","ABC","DEF"
"456","GHI","JKL"
"123","MNO","PQR"
...

一个人基于 ID 是唯一的。

CSV 的读取方式如下:

using (StreamReader sr = new StreamReader(inputFile))
{
    string[] arrCsvData;
    string strLine;

    while ((strLine = sr.ReadLine()) != null)
    {
        arrCsvData = strLine.Split(',');
        this.LoadPersonData(arrCsvData);
    }
 }

LoadPersonData一个新Person对象中创建并分配来自 CSV 的值:

Person objPerson = new Person();
for (int i = 1; i <= arrCsvData.Length - 1; i++)
{
    // Assign person property values from arrCsvData
}

我有一个字典对象,其中键是 ID,值是 Person 对象。

if(!this.PersonDataCollection.ContainsKey(personKey))
{
    this.PersonDataCollection.Add(objPerson);
}

这为我提供了 CSV 文件中所有唯一的 Person 对象。

我想创建一个基于 CSV 中的 Id 重复的 Person 对象的列表。所以列表DuplicatePersons将有:

"123","ABC","DEF"
"123","MNO","PQR"

在里面。

最基本的方法是首先将所有人员对象读入一个列表,然后执行 LINQ 查询以将所有重复项放在一个单独的列表中。这样我必须创建一个额外的集合来获取重复项。

应该有比创建单独列表更好的方法。

任何指针?

4

4 回答 4

0

为什么此时不检查这些值是否已经存在。

Person objPerson = new Person();
for (int i = 1; i <= arrCsvData.Length - 1; i++)
{
      // Assign person property values from arrCsvData
}

在此处检查您的状况,并在此时对重复值做任何您想做的事情。

于 2013-03-05T04:45:43.550 回答
0

无论你做什么.. 总会有一个单独的列表。不过,这取决于您希望它们如何出现。

选项 1 - 临时清单


每次查询现有字典时,都会返回一个内存结果。取决于您的数据集有多大。这可能不是您所追求的。

选项 2 - 静态列表


为什么不在此时维护自己的列表?:

if(!this.PersonDataCollection.ContainsKey(personKey))
{
    this.PersonDataCollection.Add(objPerson);
}
else
{
    // Create a new dictionary for the duplicates
    this.DuplicatePersonDataCollection.Add(objPerson);
}
于 2013-03-05T04:49:21.593 回答
0

首先,我会使用LINQToCSV. 解析 CSV 文件比仅仅通过,. 您不需要编写任何代码,只需创建您的类,并在其上放置属性:

class Person
{
    [CsvColumn(Name = "ID", ...)]
    string Id { get; set; }
    [CsvColumn(Name = "First Name", ...)]
    string FirstName { get; set; }
    [CsvColumn(Name = "Last Name", ...)]
    string LastName { get; set; }
}

然后,当您使用 读取文件时LINQToCSV,您会得到一个IEnumerable<Person>... 然后您可以执行以下操作:

IEnumerable<Person> people = ... //read here using LINQToCSV
var grouped = people.GroupBy(p => p.Id);

如果您在运行时知道唯一列,则可以执行以下操作:

string columnName = "Id";
persons.GroupBy(x => x.GetType().GetProperty(columnName).GetValue(x, null));

虽然你必须看看它对你的表现有多大影响。另一种不需要反射的方法可能是:

Dictionary<string, Func<Person, object>> selectors = new Dictionary <string, Func<Person, object>>
            {
                {"Id", x => x.Id},
                {"FirstName", x => x.FirstName},
                {"LastName", x => x.LastName},
            };

string columnName = "Id";
var grouped = people.GroupBy(selectors[columnName]);

现在,使用你的方法......创建另一个字典有什么问题?

你可以有类似的东西:

//Here you will store the duplicated person
//Key: The person Id
//Value: The list of person sharing that same Id
Dictionary<string, IList<Person>> duplicatedPeople;


if(!this.PersonDataCollection.ContainsKey(personKey))
{
    this.PersonDataCollection.Add(objPerson);
}
else
{
    //Here we store all the people with this already existing ID
    IList<Person> duplicatedPeople;

    //If we already have this ID in the dictionary of repeated people
    if (this.duplicatedPeople.TryGetValue(personKey, out duplicatedPeople)) {
        //Just add this new person
        duplicatedPeople.Add(objPerson);
    }
    //If this is the 1st time we found a duplicated person with this ID
    else {
        //We add two persons to the list: this one, and the one from PersonDataCollection.
        duplicatedPeople = new List<Person> { this.PersonDataCollection[personKey], objPerson };
        //Add it to the dictionary
        this.duplicatedPeople.Add(personKey, duplicatedPeople);
    }
}
于 2013-03-05T04:49:28.907 回答
0

为所有人创建一个列表,而是使用 LINQ 查询它以获得结果:

IE:

var persons = new List<Person>();
persons.Add(new Person { Id = "123", FirstName = "AAA", LastName = "XXX" });
persons.Add(new Person { Id = "123", FirstName = "BBB", LastName = "WWW" });
persons.Add(new Person { Id = "456", FirstName = "CCC", LastName = "XXX" });
persons.Add(new Person { Id = "456", FirstName = "DDD", LastName = "YYY" });
persons.Add(new Person { Id = "789", FirstName = "EEE", LastName = "ZZZ" });

var duplicateKeys = persons.GroupBy(p => p.Id).Select(g => new { g.Key, Count = g.Count() }).Where(x => x.Count > 1).ToList().Select(d => d.Key);
var duplicatePersons = persons.Where(p => duplicateKeys.Contains(p.Id)).ToList();
var unique = persons.GroupBy(p => p.Id).ToList();
于 2013-03-05T05:05:02.307 回答