2

データテーブルを別のデータテーブルに変換する必要があります。これには、主にソースデータテーブルを別の形式に転置することが含まれます。順次考えてみると、以下のように実装しました。

DataTable riskTable;
this.InitializeRmmRiskTable(out riskTable); // Initializes the columns

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
                  where tradeRow["TradeID"] != null
                  select new
                          {
                              ROW_ID = 0,
                              TCN = tradeRow["TradeID"].ToString(),                               
                              CCY = tradeRow["CURRENCY"],                                 
                              USD_VALUE = calculator.Invoke(tradeRow) // configured delegate that will fetch the value
                          }).Distinct();

foreach (var rowData in calculatedRisk)
{
    DataRow rowToAdd = riskTable.NewRow();

    rowToAdd["ROW_ID"] = rowData.ROW_ID;
    rowToAdd["TCN"] = rowData.TCN;
    rowToAdd["CCY"] = rowData.CCY;
    rowToAdd["USD_VALUE"] = rowData.USD_VALUE;

    riskTable.Rows.Add(rowToAdd);
}
return riskTable;

メモリフットプリントと実行サイクルの観点からこれを最適化するための提案はありますか?

4

3 に答える 3

2

コードを変更せずにいくつかのヒント:

文字列 ID 名の代わりにインデックスを使用します。

rowToAdd["ROW_ID"] = rowData.ROW_ID;

私は提案します

rowToAdd[0] = rowData.ROW_ID;

もう 1 つのヒントは、 object を作成する代わりに、DataRow rowToAddすべての要素について、オブジェクトの宣言を反復の外に置くことです。

また、foreach を使用する代わりに、for を使用します。

さらに

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
              where tradeRow["TradeID"] != null
              select
                  new
                      {
                          ROW_ID = 0,
                          TCN = tradeRow["TradeID"].ToString(),                               
                          CCY = tradeRow["CURRENCY"],                                 
                          USD_VALUE = calculator.Invoke(tradeRow) // configured delegate that will fetch the value
                      }).Distinct();

オブジェクトの 1 つの宣言にそのようなモンスターを使用する代わりに、この文を完全に変更します。ベイビー ステップで行うことをお勧めします。または、データに直接アクセスできる場合は、SQL 文を使用してデータをフィルタリングして取得します。

そして、ジェネリックの代わりに正確なタイプのデータを使用しますvar

より複雑な変更には、コードについて詳しく知る必要があります...

于 2012-10-30T10:19:05.217 に答える
2

多くの列ルックアップを簡単に削除できます。

object[] values = new object[4];
foreach (var rowData in calculatedRisk)
{
    values[0] = rowData.ROW_ID;
    values[1] = rowData.TCN;
    values[2] = rowData.CCY;
    values[3] = rowData.USD_VALUE;

    riskTable.Rows.Add(values);
}

これは、列の順序を知っていることを前提としています。それ以外の場合は、DataColumnAPI が最も直接的であるため、4 を保存DataColumnしてインデクサーで使用できます。これは読み取りコードにも同様に適用されます。

var tradeId = tradeTableToFilter.Columns["TradeID"];
var currency = tradeTableToFilter.Columns["CURRENCY"];

それから:

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
    let tradeIdVal = tradeRow[tradeId]
    where tradeIdVal != null
    select new {
        ROW_ID = 0,
        TCN = tradeIdVal.ToString(),                               
        CCY = tradeRow[currency],                                 
        USD_VALUE = calculator.Invoke(tradeRow)
    }).Distinct();

を使用Distinctすると、すべてのオブジェクトが再びメモリにバッファリングされます。これが必要であることがわかっている場合は問題ありませんが、多くの場合、これは冗長になる可能性があります。

于 2012-10-30T10:14:31.867 に答える
1

(コメント)あなたは戻り値の型を変更するオプションを受け入れていると述べているので、私は次のように宣言します:

public class TradeRisk {
    public int Id {get;set;}
    public string TCN {get;set;} // expand name to be meaningful
    public string Currency {get;set;}
    public decimal UsdValue {get;set;}
}

メソッドを return に変更しList<TradeRisk>ます。前の回答と同じDataColumnトリックを適用できますが、結果を変更できます。結果を同じに保つには、Distinctなどを保持する必要があることに注意してください。

var tradeId = tradeTableToFilter.Columns["TradeID"];
var currency = tradeTableToFilter.Columns["CURRENCY"];

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
    let tradeIdVal = tradeRow[tradeId]
    where tradeIdVal != null
    select new {
        Id = 0,
        TCN = tradeIdVal.ToString(),                               
        Currency = tradeRow[currency],                                 
        UsdValue = calculator.Invoke(tradeRow)
    }).Distinct();

return (from row in calculatedRisk 
        select new TradeRisk {
            Id = row.Id, TCN = row.TCN,
            Currency = row.Currency,
            UsdValue = row.UsdValue
        }).ToList();

DataTableこれにより、すべてのオーバーヘッドが回避されます。本当に必要な場合は、 を実装して、次のようにすることもできTradeRisk : IEquatable<TradeRisk>ます。

return (
    from DataRow tradeRow in tradeTableToFilter.Rows
    let tradeIdVal = tradeRow[tradeId]
    where tradeIdVal != null
    select new TradeRisk {
        Id = 0,
        TCN = tradeIdVal.ToString(),                               
        Currency = tradeRow[currency],                                 
        UsdValue = calculator.Invoke(tradeRow)
    }).Distinct().ToList();
于 2012-10-30T10:35:22.117 に答える