0

私は100万個の要素の配列を持っており、現在のインデックスを「今」として作成し、それをインクリメントして新しいデータをシミュレートすることにより、ライブデータとしてシミュレートします。

現在のデータと過去のデータXバーについて多くの計算を行います。

someDataType[0]および1バー前のsomeDataType[1]などで今日のデータにアクセスするためにこれを抽象化する便利な方法があるかどうか疑問に思っていますか?

私はプログラミングに不慣れなので、何が可能で何が不可能かはよくわかりません。理想的には、このデータ型は配列からデータ型にデータをコピーする必要はなく、すべてのデータ自体を格納して配列をスキップするか、何らかの方法で配列を指すことができます。そして、それは間違いなく配列と同じ方法でデータにアクセスできなければならず、リストが必要とするようなあるポイントに到達するためにそれ自体を反復する必要はありません。

これが何らかの形、形、形で可能かどうか、私にはまったくわかりません。したがって、私は尋ねています。ご入力いただきありがとうございます。:)

4

3 に答える 3

4

まず、新しいアイテムを追加する場合は、配列を直接使用することはおそらく最善の選択ではありません(最新のアイテムが最も古いアイテムを上書きする必要がある場合を除く)。より良い選択はList<T>です。

ここで、作成するのは「反転」コレクションです。これには、とが含まれますList<T>

  • そのインデクサーは、バッキングリストのリバースインデックスにアクセスします
  • そのaddメソッド(おそらく呼び出されるAddFirst())はリストの最後に追加されます
  • そのGetEnumerator()メソッドは逆列挙子を返します

これらすべての要件が具体化されると、コードはほとんどそれ自体を記述します。

class AddFirstList<T> : IEnumerable<T>, IReadOnlyList<T>
{
    private readonly List<T> m_list = new List<T>();

    public void AddFirst(T item)
    {
        m_list.Add(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return Enumerable.Reverse(m_list).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public int Count
    {
        get { return m_list.Count; }
    }

    public T this[int index]
    {
        get { return m_list[Count - index - 1]; }
    }
}

(.Net 4.5を使用していない場合は、IReadOnlyList<T>インターフェイスを削除してください。)

于 2013-02-15T00:46:18.210 に答える
0

構造に動的なサイズ設定が必要なようです。そのためList<T>、System.Collections.Generic名前空間に適切な選択があります。

var list = new List<int>();
list.Add(1); // keep adding

配列と同じようにインデックス付きアクセスを提供しますが、必要に応じて要素を追加し続けることができます。(インデックスを介した通常のランダムアクセスに加えて)最後の要素をすばやく取得するだけの場合は、インターフェイス用に最適化さLast()れた拡張メソッド(および実装するもの)を使用して、最後の要素を直接返すことができます。シーケンス全体を列挙する必要のない要素。IList<T>List<T>

ただし、完全な逆インデックスアクセスに似たものが必要なようです。そのためには、コーディングする必要があるかもしれません。再利用性のために、これをプロジェクトの拡張メソッドにして、必要な場所で使用できます。このようなものはあなたのニーズに合うはずです。

public static class ListExtensions
{
    public static T FromEnd<T>(this IList<T> list, int position)
    {
        if (list == null || list.Count == 0)
        {
            throw new ArgumentException("list cannot be null or empty");
        }

        return list[(list.Count - 1) - position];
    }
}

そしてそれを使うのは簡単です。

var myList = new List<int>() { 1, 2, 3, 4, 5 };
int item = myList.FromEnd(1);
Debug.Assert(item == 4);

もちろん、ここでのしわは、foreach(標準を使用することもできますfor)でループしたい場合、これはうまく機能しないことです。foreachを使用する場合は、単にuseforeach (var item in myList.Reverse()) { }をループするか、svickの回答にコード化されているアプローチを利用できます。

于 2013-02-15T00:45:40.557 に答える
0

インデックス0を「現在のデータ」にし、インデックス1を前のデータにしたいようです。

これは、百万要素の配列をカプセル化する独自のクラスを作成することで実現できます。次に、あるインデックスを指定して、right nowそれをすべてのインデックスに追加できます。例えば:

public class DataArray
{
    readonly Object[] data;

    int rightNow;
    public int RightNow
    {
        get { return this.rightNow; }
        set { this.rightNow = value; }
    }

    public DataArrat(Object[] data)
    {
        // TODO: Check that data is not null.
        this.data = data;
    }

    // This is called an 'indexer':
    public Object this[int index]
    {
        get
        {
            // TODO: Check whether (index + this.rightNow) is in the valid range.
            return this.data[index + this.rightNow];
        }
    }
}

これで、たとえば次のように使用できます。

// Initialize the DataArray:
Object[] millionElementArray /* = from somewhere, e.g. */ = new []
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var data = new DataArray(millionElementArray);

// Start at bar 8:
data.RightNow = 8;

// Use the data:
Object currentData = data[0];
Object futureData = data[-1];
Object pastData = data[1];

// Go to the next bar:
data.RightNow--;

// Use the data:
Object currentData = data[0];
Object futureData = data[-1];
Object pastData = data[1];

// Rinse and repeat...

Object使用しているデータのタイプに置き換えるか、クラスをジェネリックにする必要があることに注意してください。

于 2013-02-15T00:55:36.433 に答える