8

整数 (または任意のクラス T) のキューがある場合、キュー内の要素の値を変更できますか? より具体的には、次のようにキューを定義すると:

Queue<int> q = new Queue<int>();

配列を扱う方法と同様に、その要素の値を変更できますか? (q が配列の場合、次のようなことができます:q[0]=1その要素を変更します)。シナリオを単純化し、例として int を使用したいだけですが、私の意図は、キュー内のクラス T の最初の項目を覗いて、いくつかの計算を行い、他のプログラムが処理できるようにキューを更新することでした。キュー内のシーケンスが元のシーケンスと同じでなくなるため、デキューしたくありません。やろうとしていることが理にかなっていることを願っています。お知らせ下さい。

4

6 に答える 6

8

キュー内のアイテムが変更可能なタイプの場合、キューが最初のアイテムとして持つ値を変更できます。キューを再作成するか、多くのエンキュー/デキューを実行しない限り、キューの先頭にあるアイテムを変更する方法はありません。

最初のケースの例として、次Queue<MyClass>の定義を持つがあるとします。

class MyClass
{
    public string Value { get; set; }
}

Queue<MyClass> queue = new Queue<MyClass>();
queue.Enqueue(new MyClass() { Value = "1" });
queue.Peek().Value = 2;
string value = queue.Peek().Value; // is 2
于 2012-09-11T14:31:06.847 に答える
5

アイテムを直接変更することはできませんQueue(ただし、Tudor が提案した回避策を使用できます)。ただし、キューが必要な場合は、を使用する必要はありませんQueue。.Net の別の可能なタイプは ですLinkedList。これにより、シナリオで使用できる両端からのものを追加および削除できます。

LinkedList<int> list = new LinkedList<int>();

// enqueue an item
list.AddLast(1);

// dequeue an item
var item = list.First.Value;
list.RemoveFirst();

// put item back to the front of the queue
list.AddFirst(item);

各アイテムを複数のモジュールで順番に処理するには、これを行いたいようです。しかし、これがこの種の作業を行う正しい方法であるかどうかはわかりません。より良い方法は、2 つのモジュールごとにキューを作成することです。モジュールは常に入力キューからアイテムを取得し、それを処理してから出力キューに入れます。

このアプローチの利点の 1 つは、柔軟性が高いことです。モジュールは、入力とは異なる型を出力に持つことができます。これは、「キューが 1 つ」のアプローチでは不可能です ( objects のキューなどに頼らない限り)。それ)。

TPL データフロー (.Net 4.5 の新機能) は、このアプローチを使用して、並列化によってパフォーマンスを向上させます。単一の中央キューがない場合、各モジュールは他のモジュールとは独立してアイテムを処理できるため、それが可能です。

于 2012-09-11T14:50:15.463 に答える
2

クラスのような参照型を保存している限り、それに加えた変更はキューに反映されます。以下のコードの出力は「2」になります。

    public class MyClass
    {
        public int Value { get; set; }
    }

    static void Main(string[] args)
    {
        Queue<MyClass> q = new Queue<MyClass>();
        q.Enqueue(new MyClass { Value = 1 });
        var i = q.Peek();
        i.Value++;
        i = q.Peek();
        Console.WriteLine(i.Value);
    }
于 2012-09-11T14:40:06.823 に答える
1
    public static class Extensions
    {
        public static Queue<T> SetFirstTo<T>(this Queue<T> q, T value)
        {
            T[] array = q.ToArray();
            array[0] = value;
            return new Queue<T>(array);
        }
    }

厳密には、これはキューを変更していないため、再割り当てが必要です。

        [TestMethod]
        public void Queue()
        {
            var queue = new Queue<int>(new[]{1,2,3,4});
            queue = queue.SetFirstTo(9);
            Assert.AreEqual(queue.Peek(),9);
        }
于 2012-09-11T15:19:58.610 に答える
1

シンプルなラッパーを使用できます。

class Wrapper<T>
{
    public T Value { get; set; }
}

static void Main(string[] args)
{
    Queue<Wrapper<int>> q = new Queue<Wrapper<int>>();
    Wrapper<int> wr = new Wrapper<int> { Value = 1 };
    q.Enqueue(wr);

    Wrapper<int> wr1 = q.Peek();
    wr1.Value = 2;

    int value = q.Dequeue().Value;
    Console.WriteLine(value);
}
于 2012-09-11T14:32:39.170 に答える
-3

簡単な答えはノーです。Queue オブジェクトの API の一部ではありません

http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx

ただし、もちろん何でも可能です。これを行う拡張メソッドを作成することもできますが、オブジェクトの API を操作する必要があるため、順序を維持しながら、変更と共にすべての項目をデキュー/エンキューする必要があります。

しかし、これを行いたい場合は、キューをリストとして扱っているので、リストを使用しないのはなぜですか?

于 2012-09-11T14:30:39.750 に答える