2

編集:重要なポイントを逃しました:.NET 2.0

次のようなタイプを単純にするために、ソートされていないアイテムのリストがある場合を考えてみましょう。

class TestClass
{
    DateTime SomeTime;
    decimal SomePrice;

    // constructor
}

毎日の合計価格が累積されるレポートのような出力を作成する必要があります。項目ごとに 1 つの行があり、その後に適切な要約行が続きます。

次のテスト データを取得します。

List<TestClass> testList = new List<TestClass> { 
new TestClass(new DateTime(2008,01,01), 12),
new TestClass(new DateTime(2007,01,01), 20),
new TestClass(new DateTime(2008,01,01), 18)
};

望ましい出力は次のようになります。

2007-01-01: 
20
Total: 20

2008-01-01: 
12
18
Total: 30

そのようなシナリオにアプローチする最善の方法は何ですか? このようなリストの場合、リストをソートできるように、TestClass の IComparable インターフェイスを実装します。

レポート自体を作成するには、次のようなものを使用できます (価格の累積、現在の日付の追跡などのタスクのためのメソッドがあると仮定しましょう):

for (int i=0;i<testList.Count;i++)
{
    if (IsNewDate(testList[i]))
    {
        CreateSummaryLine();
        ResetValuesForNewDate();
    }

    AddValues(testList[i]);
}

// a final summary line is needed to include the data for the last couple of items.
CreateSummaryLine();

これで問題なく動作しますが、2 番目の「CreateSummaryLines」に関する限り、私は奇妙な感覚を覚えます。

そのような状況をどのように処理しますか (特に、事前に分類された辞書などではなく、アイテムの List<> を操作する必要があるという事実を考慮して)?

4

6 に答える 6

3

さて、LINQ を使用できない場合:

(スペースを節約するために var を使用していますが、必要に応じて C# 2.0 に変換するのは簡単です...)

var grouped = new SortedDictionary<DateTime, List<TestClass>>();
foreach (TestClass entry in testList) {
  DateTime date = entry.SomeTime.Date;
  if (!grouped.ContainsKey(date)) {
    grouped[date] = new List<TestClass>();
  }
  grouped[date].Add(entry);
}

foreach (KeyValuePair<DateTime, List<TestClass>> pair in testList) {
  Console.WriteLine("{0}: ", pair.Key);
  Console.WriteLine(BuildSummaryLine(pair.Value));
}
于 2008-10-17T12:55:41.317 に答える
2

重要な質問: .NET 3.5 を使用しているため、LINQ を使用できますか? その場合は、SomeTime.Date でグループ化し、各日付を個別に処理できます。

大量のデータがある場合は、私のPush LINQプロジェクトが役立つかもしれませんが、それ以外の場合は、直接的な LINQ to Objects が最善の策です。

于 2008-10-17T12:46:44.890 に答える
2

[編集] C# 3.0 で .NET 2.0 を使用しているため、 LINQBridgeを使用してこれを有効にすることができます。

リンク; 何かのようなもの:

        var groups = from row in testList
                  group row by row.SomeTime;
        foreach (var group in groups.OrderBy(group => group.Key))
        {
            Console.WriteLine(group.Key);
            foreach(var item in group.OrderBy(item => item.SomePrice))
            {
                Console.WriteLine(item.SomePrice);
            }
            Console.WriteLine("Total" + group.Sum(x=>x.SomePrice));
        }
于 2008-10-17T12:46:54.813 に答える
1

使用している C#/.NET のバージョンは何ですか? 最新の場合は、LINQ をご覧ください。これにより、データをグループ化できます。あなたの場合、日付でグループ化できます:

var days = from test in testList group test by test.SomeTime;
foreach (var day in days) {
    var sum = day.Sum(x => x.SomePrice);
    Report(day, sum);
}

dayこのようにして、各 の値のリストと、その日の金額を報告できます。

于 2008-10-17T12:46:55.967 に答える
0

レポート出力の生成方法に関係なく、アプリケーションでこれを定期的に行う場合は、レポート インターフェイスをまとめて、このインターフェイスのクラスを実装し、レポートを作成するためのロジックを 1 か所にローカライズすることを検討してください。アプリケーション全体でレポートを作成します。私の経験では、通常、アプリケーションには複数のレポート、そして最終的には複数の形式に対する要件があります (または増加します)。

レポートが 1 つしかない場合は、2 つ目のレポートを作成するまで心配する必要はありません。それから、拡張と保守を容易にするレポート アーキテクチャの作業を開始してください。

例(および@Marc Gravellのコードを使用):

public interface IReport
{
   string GetTextReportDocument();
   byte[] GetPDFReportDocument();  // needing this triggers the development of interface
}

public class SalesReport : IReport
{
   public void AddSale( Sale newSale )
   {
       this.Sales.Add(newSale);  // or however you implement it
   }

   public string GetTextReportDocument()
   {
       StringBuilder reportBuilder = new StringBuilder();
       var groups = from row in this.Sales
                    group row by row.SomeTime.Date;
       foreach (var group in groups.OrderBy(group => group.Key))
       {            
          reportBuilder.AppendLine(group.Key);
          foreach(var item in group.OrderBy(item => item.SomePrice))            
          {
             reportBuilder.AppendLine(item.SomePrice);
          }
          reportBuilder.AppendLine("Total" + group.Sum(x=>x.SomePrice));
      }

      return reportBuilder.ToString();
   }

   public byte[] GetPDFReportDocument()
   {
        return PDFReporter.GenerateDocumentFromXML( this.ConvertSalesToXML() );
   }

...残りは読者の演習として残します...

于 2008-10-17T13:52:50.733 に答える
0

目的の出力は、要約データを表すデータ構造を作成したいような気がします。日付を TestClass オブジェクトのリストとペアにして、それらのコレクションを取得します。コレクションには HashSet または Dictionary を使用できます。

要約すると、ペア データ構造は ToString を実装できます。

于 2008-10-17T12:47:29.337 に答える