user1205746
user1205746

Reputation: 3364

Is it possible to change an element in a queue?

Let say if I have a queue of integer (or any class T), can I change the value of the element in the queue? More specifically, if I define the queue as follow:

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

Can we change the value of its element similar to how we deal with an array? (if q were an array, we would be able to do something like this: q[0]=1 to change its element). I just would like to simplify the scenario and use int as example, but my intention was trying to peek at the 1st item of a class T in a queue, do some calculations and update the queue for other programs to process. I do not want to dequeue it because it the sequence in the queue will then not be the same as the original. Hope what am trying to do make sense. Please advise.

Upvotes: 10

Views: 28318

Answers (6)

Yoztastic
Yoztastic

Reputation: 862

    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);
        }
    }

Strictly this is not mutating the Queue so re-assignment required.

        [TestMethod]
        public void Queue()
        {
            var queue = new Queue<int>(new[]{1,2,3,4});
            queue = queue.SetFirstTo(9);
            Assert.AreEqual(queue.Peek(),9);
        }

Upvotes: 1

svick
svick

Reputation: 244837

You can't directly change an item in Queue (although you can use a workaround as Tudor suggested). But if you want to have a queue, you don't have to use Queue. Another possible type from .Net is LinkedList. It allows you to add and remove things from both ends, which can be used in your scenario:

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);

It seems you want to do this to process each item by several modules in sequence. But I'm not sure this is the right way to do this kind of work. A better way might be to have a queue between each two modules. A module would always take an item from its input queue, process it and then put it in its output queue.

One of the advantages of this approach is greater flexibility: a module can have different type on the output than on the input, which is not possible with the “one queue” approach (unless you resort to having a queue of objects, or something like that).

TPL Dataflow (new in .Net 4.5) uses this approach to improve performance through parallelization. It can do that, because each module can process items independently of other modules if you don't have a single central queue.

Upvotes: 7

Mike Payne
Mike Payne

Reputation: 624

As long as you're storing a reference type like a class, any changes you make to it will be reflected in the Queue. The output of the code below will be "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);
    }

Upvotes: 3

Tudor
Tudor

Reputation: 62439

You could use a simple wrapper:

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);
}

Upvotes: 2

James Gaunt
James Gaunt

Reputation: 14783

The simple answer is no. It's not part of the API of Queue object

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

However anything is possible of course. You could write an extension method to do this, but it would have to work with the API of the object and so dequeue / enqueue all items along with the change whilst preserving the order.

But if you want to do this, you are treating the Queue as a List, so why not use a List?

Upvotes: -3

Servy
Servy

Reputation: 203834

If the item in the queue was a mutable type then you could change the value that the queue has as it's first item. Without re-creating the queue, or performing a lot of enqueues/dequeues there is no way to change which item is at the front of the queue.

As an example of the first case, if you had a Queue<MyClass> with a definition of:

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

Upvotes: 9

Related Questions