3

独自の統計 (すべての Result 統計に基づく ResultGroup クラスの統計) を持つオブジェクトのリストの最大、最小、および平均 (統計) 値を見つける必要があります。オブジェクトを追加すると値は簡単に更新されますが、そのうちの 1 つを変更または削除すると、もう一度統計を見つける必要があります。通常は 40.000 を超えるアイテムがあり、迅速な操作が必要です。

すべてのアイテムをループするよりも良い方法はありますか?

public class ResultGroup
{
    private Stats resultStats;
    //I need an updated stats
    public Stats ResultStats
    {
        get { return resultStats; }
    }
    private readonly ObservableCollection<Result> results = new ObservableCollection<Result>();

    public ObservableCollection<Result> Results
    {
        get
        {
            return results;
        }
    }
    public ResultGroup()
    {
        this.resultStats = new Stats();
        this.results.CollectionChanged += new NotifyCollectionChangedEventHandler(CollectionChanged);
    }

    private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            //It works ok on add.
            Stats lastResultStat = this.results[this.results.Count - 1].Stat;
            if (resultStats.Max < lastResultStat.Max)
                resultStats.Max = lastResultStat.Max;

            if (resultStats.Min > lastResultStat.Min)
                resultStats.Min = lastResultStat.Min;

            resultStats.Mean = (resultStats.Mean * (this.results.Count - 1) + lastResultStat.Mean) / this.results.Count;
        }
        else if (e.Action == NotifyCollectionChangedAction.Reset)
        {
            this.resultStats = StatsFactory();
        }
        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            //Need to find the stats here
        }
        else if (e.Action == NotifyCollectionChangedAction.Replace)
        {
            //Need to find the stats here
        }
    }

    private Stats StatsFactory()
    {
        Stats dataStats = new Stats();
        dataStats.Max = float.MinValue;
        dataStats.Min = float.MaxValue;
        dataStats.Mean = 0;
        return dataStats;
    }
}

public class Result
{
    private float[] data;

    //Another class will fill data and set the Stats (max, min, mean)
    public float[] Data
    {
        get { return data; }
    }

    public Result(int lenght)
    {
        this.data = new float[lenght];
    }

    private Stats stat;
    public Stats Stat
    {
        get { return stat; }
        set { stat = value; }
    }
}

public class Stats
{
    public float Max { get; set; }
    public float Min { get; set; }
    public float Mean { get; set; }
}
4

5 に答える 5

3

アイテムを削除するときは、削除されたアイテムが現在の最小/最大と等しい場合にのみ、すべてのアイテムをループする必要があります。

アイテムを置き換えるときは、削除されたアイテムが現在の最小値/最大値と等しく、新しいアイテムの方が大きい/小さい場合にのみ、すべてのアイテムをループする必要があります。

于 2012-05-15T12:59:24.583 に答える
1

CollectionChanged 内で Min、Max、Average などの LINQ 演算子を使用しようとしましたか?

于 2012-05-15T12:42:17.317 に答える
1

最初にコレクションを初期化するときに最大値、最小値をキャッシュしてから、新しい値とキャッシュされた値を比較できると思います。

次のアルゴリズムを提案できます。値のリストが膨大な場合は、それを範囲で分割し、範囲ごとにコレクションを作成します。コレクションごとに、コレクションが変更されたときに再計算されるキャッシュされた平均値があります。新しい値を追加 (または変更) すると、要素の統計が表示され、必要な範囲のコレクションが見つかります。この状況では、追加のインデックスとして統計を取得し、特定のコレクション (最初、最後) でのみ最大値と最小値を見つける必要があります。すべてのコレクションの平均値から取得できる平均値。最初と最後のコレクションにもキャッシュできる最大値、最小値。

于 2012-05-15T12:44:33.950 に答える
1

これにDBを使用しようとしましたか?

DBには役立つ索引付けがあるためです。また、数ミリ秒で数百万行を透過する垂直/列ベースのDBを備えたKDBまたはSAPのHANAもご覧ください。

おそらく、SqlLite のような単純なファイル ベースの DB が役立つでしょう。(大量のデータを扱っている場合、これはメモリ使用量の削減にも役立ちます)

于 2012-05-15T12:45:25.377 に答える
0

//コレクション内に必要なプロパティを持つカスタム コレクションを用意し、コレクションの上に linq を配置して集計値を格納することをお勧めします...

 public class ObserCol: ObservableCollection<int>
{

    private int _maxValue = 0;

    public ObserCol() { 
        base.CollectionChanged +=new NotifyCollectionChangedEventHandler(CollectionChanged);
    }

    public int MaxValue{
        get {
            return _maxValue;
        }
    }

    private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            //Can use Linq to get the Max or Other Aggregate values..
        }
        else if (e.Action == NotifyCollectionChangedAction.Reset)
        {

        }
        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {

        }
        else if (e.Action == NotifyCollectionChangedAction.Replace)
        {

        }
    }
}
于 2012-05-15T13:31:05.260 に答える