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

すべての人に対して単一のリストを作成し、LINQ でクエリを実行して結果を取得します。

すなわち:

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 に答える
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 に答える