1

重複の削除に関する情報はたくさん見つかりましたが、以下の問題に関するガイダンスはどこにも見つかりませんでした...

CSV からインポートした C# DataTable の重複する行の名前を変更する方法を探しています。私のデータは次のようになります。

**Name**       **Item**                 **Quantity**
ABC            Item_Name                     6
ABC            Item_Name_2                   1
DEF            Item_Name                     3
GHI            Item_Name_2                   7
ABC            Item_Name                     6
ABC            Item_Name                     1
JKL            Item_Name_3                   4
ABC            Item_Name                     6
ABC            Item_Name                     1
JKL            Item_Name_3                   4

行全体(数量を含む)が複数回表示される場合、データをどのように表示したいかは次のとおりです。

**Name**          **Item**                 **Quantity**
ABC            Item_Name                        6
ABC            Item_Name_2                      1
DEF            Item_Name                        3
GHI            Item_Name_2                      7
ABC (2)        Item_Name                        6
ABC (2)        Item_Name_2                      1
JKL            Item_Name_3                      4
ABC (3)        Item_Name                        6
ABC (3)        Item_Name_2                      1
JKL (2)        Item_Name_3                      4

現在、二重の「for ループ」を使用して、テーブルのさらに下にあるどの行が現在の行と同じデータを持っているかを判断し、それに応じて名前を変更しています。明らかに、これには 2 つの問題があります。

  1. 明らかに、多数の行を持つテーブルでは本当に遅いです

  2. 名前列が「ABC」だった将来のすべての行には、これが最初の 2 番目または 98 回目の発生であるかどうかに関係なく、名前列「ABC (2)」が含まれるようになりました (率直に言って、私のコードは最悪です)。

誰でも提供できるヘルプは大歓迎です:)

4

2 に答える 2

2
    foreach(DataRow row in thisTable.Rows)
    {
        string name = row.Item[0].ToString();

        if(name[name.Length - 3] == '(' && name[name.Length - 1] == ')')
            continue;

        string item = row.Item[1].ToString();
        int quantity = Convert.ToInt32(row.Item[2]);
        string expression = "Name = " + name + " and Item = " + item + " and Quantity = " + quantity;

        DataRow[] matchingRows = table.Select(expression);
        for(int i = 1; i < matchingRows.Length; i++)
            matchingRows[i]["Name"] += " (" + i + ")";  
    }

基本的に、各行をループするだけです。次に、同一のすべての行を照会します。次に、それらの同一の行をループし、(1)、(2)、(3) などの文字列を追加して名前を変更します (クエリで見つかった順序で)。その「if」ステートメントで既に名前を変更した行もスキップします(名前が変更された行は、最後の文字から3番目の文字が「(」で終わり、最後の文字が「)」で終わると想定しています)。コードに C# 構文関連のエラーがありましたら申し訳ありません。ただし、アイデアは非常に簡単です。

于 2013-05-28T14:34:15.827 に答える
0

ここに別の解決策があります。私の意見では、よりエレガントです!

        DataTable table = new DataTable();
        table.Columns.Add("Name", typeof(string));
        table.Columns.Add("Title", typeof(string));
        table.Columns.Add("Quantity", typeof(int));

        // Data for test
        table.Rows.Add("ABC", "Item_name", 6);
        table.Rows.Add("ABC", "Item_name", 6);
        table.Rows.Add("ABC2", "Item_name", 6);
        table.Rows.Add("ABC2", "Item_name", 6);
        table.Rows.Add("ABC2", "Item_name", 6);
        table.Rows.Add("ABC2", "Item_name", 6);

        // Query with Linq
        var query = from row in table.AsEnumerable()
                    group row by new {
                        name  = row.Field<String>("Name"),
                        title = row.Field<String>("Title")
                    } into GrpNameTitle
                    select new {
                        Name  = GrpNameTitle.Key.name + " (" + GrpNameTitle.Count() + ")", 
                        Title = GrpNameTitle.Key.title,
                        Quantity = GrpNameTitle.First().Field<int>("Quantity")
                    };


        foreach (var itm in query)
        {
            Console.WriteLine("{0}\t{1}", itm.Name, itm.Title);
        }

質問があります。2 つの列 (名前とタイトル) で行を「グループ化」してフィルター処理すると、3 番目の列に数量が含まれていることを追加/計算しても意味がありませんか? 例えば:

abc item_name 2
abc item_name 2

この結果を与える:

abc(2) item_name 4

よろしくお願いします、

メンター・レカ。

于 2013-05-28T15:01:21.897 に答える