sort a queue in C#

16,137

Solution 1

Why would you want to order by the type of object in a queue? A queue, by its definition, it's not meant to be ordered in that way but intended to work as a first in first out kind of element.

Either use a List if you just want a collection capable of being ordered, and ordered list or create several queues for the different kind of objects that you have.

For example, if you go to the super market you have several queues, one for each different section... it wouldn't make any sense to put all people in the same queue and then "order" them based on whether they are in for the butcher or the bakery.

You have a queue when you need to "queue" things... if you don't use the appropriate construct, don't try to force it into a queue. ("if you have a hammer everything looks like a nail"... but it should not)

Solution 2

While everything that has been said about using queue and OrderBy is valid, you still might want to order elements in your queue.

You can build a new queue based on a IOrderedEnumerable:

Queue<string> queue = new Queue<string>();
queue.Enqueue("first");
queue.Enqueue("second");
queue.Enqueue("third");
queue.Enqueue("fourth");

// Builds a new queue. Items are now alphabetically ordered
Queue<string> orderedQueue = new Queue<string>(queue.OrderBy(z => z));
Share:
16,137
DevT
Author by

DevT

.net developer #SOreadytohelp - SOF helps resolve my probs

Updated on June 04, 2022

Comments

  • DevT
    DevT almost 2 years

    Even though this question sounds as a duplicate, I searched a lot but couldn't find a proper solution.

    I have following classes

    public enum ChangeType
    { 
        Add,
        Modify,
        Delete
    }
    
    
    
    public enum ChangedObjectType
    { 
        Project,
        Customer,
        Border,
        Photo
    }
    
    public struct ChangeInfo
    {
        public ChangeType typeofChange { get; private set; }
        public ChangedObjectType objectType { get; private set; }
    
        public string objectID { get; private set; }
    
        public ChangeInfo(ChangeType changeType, ChangedObjectType changeObj, string objectId):this()
        {
            typeofChange = changeType;
            objectType = changeObj;
            objectID = objectId;
        }
    
    }
    

    thread :

    public class ChangeInfoUploader
    { 
        static Queue<ChangeInfo> changeInfoQueue = new Queue<ChangeInfo>();
        static Thread changeInfoUploaderThread = new Thread(new ThreadStart(ChangeInfoUploaderProc));
        static bool isStarted = false;
        static Project currentProject;
    
        public static void Initialize(Project curproject)
        {
            currentProject = curproject;
            isStarted = true;
            changeInfoUploaderThread.Start();
            ResumeData();
        }
    
        static void ChangeInfoUploaderProc()
        {
            while (isStarted)
            {
                if (currentProject != null)
                {
                    ChangeInfo? addToDb = null;
    
                 // I need to sort changeInfoQueue before dequeue
                    lock (changeInfoQueue)
                    {
                        if (changeInfoQueue.Count != 0)
                            addToDb = changeInfoQueue.Dequeue();
                    }
                }
            }
            Logdata();
            changeInfoUploaderThread.Abort();
        }
    }
    

    here is the sample data of changeInfoQueue queue.

    <Info TypeofChange="Add" ObjectType="Customer" ObjectId="0005" />
    <Info TypeofChange="Add" ObjectType="Customer" ObjectId="0006" />
    <Info TypeofChange="Add" ObjectType="Customer" ObjectId="0007" />
    <Info TypeofChange="Add" ObjectType="Photo" ObjectId="01a243f5-4894-4d99-8238-9c4cd3" />
    

    My Question :

    • I need to sort out changeInfoQueue based on ObjectType. How can i do that?

    My findings:

    • I found OrderBy . Is it possible to use it? If so, how?

    In addition to that I found priorityQueue. What is the best solution for me?

    EDIT:

    The values of this queue are added when relevant objects are created. (projects, borders etc.) and saves it in a local XML file. After that it needs to write to a database. This is accomplished by using a thread and when we save this data it must be saved in particular order to avoid foreign key violations. So this thread is used to call those relevant methods.

    I used orderby as follows:

    Queue<ChangeInfo> changeInfoQueue2 = changeInfoQueue.OrderBy(ChangeInfo => ChangeInfo.ObjectType);
    

    then it throws following exception:

    Cannot implicitly convert type 'System.Linq.IOrderedEnumerable' to 'System.Collections.Generic.Queue'. An explicit conversion exists (are you missing a cast?)

    • Oded
      Oded over 11 years
      If you know about OrderBy, please explain how you tried to use it and where you are stuck.
    • dognose
      dognose over 11 years
      A queue is a queue - sorting a queue is pointless. Imagine the queue in the supermarket, where people get called alphabetical... Use a SortedDictionary instead. (Or if you just want to force some special entrys, look at PriorityQueues)
    • sll
      sll over 11 years
      There is no enough details about why you need this, Queue data structure has nothing about sorting, it is a set of items in order they were added, so you need to update queue order itself or just sort items in some temoporary location is fine as well?
    • subprime
      subprime over 11 years
      You can use Linq. See this article stackoverflow.com/questions/561644/queue-ordering
    • Arie
      Arie over 11 years
      Do you really need Queue class? Its main purpose is, after all, to preserve the order in which items were added. Maybe you could use List or some other collection?
    • Henk Holterman
      Henk Holterman over 11 years
      Just make it IEnumerable<ChangeInfo> changeInfoQueue2`
    • DevT
      DevT over 11 years
      @sll , - i modified my question
    • 2GDev
      2GDev over 11 years
      or "var changeInfoQueue2 = ..."
    • DevT
      DevT over 11 years
      IEnumerable<ChangeInfo> also throws exceptions
    • Henk Holterman
      Henk Holterman over 11 years
      No, those messages are compiler errors, not exceptions. Use var.
  • DevT
    DevT over 11 years
    this queue values are added when relevent objects are created. (projects, borders etc) and saved it in locally as a xml file. after that it need to write db. this is done using thread and when we save these data its need to to save in particular order in order to avoid foreign key vialations
  • Jorge Córdoba
    Jorge Córdoba over 11 years
    So? Use a list an order it properly. The problem is not that you're trying to solve the wrong problem but you're trying to use a queue for something that's better solved with other data type.
  • DevT
    DevT over 11 years
    it says "At least one object must implement IComparable." that means do i need to implement my class using IComparable?
  • ken2k
    ken2k over 11 years
    @TilT Yes. Please see this answer for details: stackoverflow.com/a/14141926/870604