-1

I am looking for a way to quickly retrieve all items out of a list. This list contains time values, and i need everything before a specific time. Obviously a list which is ordered should be easy, once you find 1 item in the list with a higher value than what you've defined it can stop.

I found this ordered queue online which claims to be fast but it does not have a good method for finding all times up to a certain point.

If i knew of a way to make this method (a good and fast one) i would, but I have no idea what the best possible way would be.

I am currently using this queue as follows, which isn't the best way to use it (I would think):

while (mDisposing == false)
{
    if (this.mIdleChoresRunning == true)
    {
        try
        {
            if ((mIdleChoreQueue.First != null) && (Timing.IsTimeOutByTicksNow(mIdleChoreQueue.First.AddTime, mIdleChoreQueue.First.WaitTime)))
            {
                //var item = mIdleChoreQueue.Dequeue();
                var chore = mIdleChores[mIdleChoreQueue.First.IdleChoreIdentification];
                mIdleChoreQueue.First.AddTime = Environment.TickCount;
                mIdleChoreQueue.First.WaitTime = chore.IdleMiliSeconds;

                mTaskQueue.EnqueueTask(() =>
                //Task.Factory.StartNew(() =>
                {
                    chore.Execute(mIdleChoreQueue.First.Context);
                });

                mIdleChoreQueue.UpdatePriority(mIdleChoreQueue.First, mIdleChoreQueue.First.AddTime + mIdleChoreQueue.First.WaitTime);
            }
            else
            {
                Thread.Sleep(10);
            }
        }
        catch (Exception exception)
        {
            mLogger.Error("ExecuteIdleChores() EXCEPTION", exception);
        }
    }
    else
    {
        Thread.Sleep(100);
    }
}

To clarify I do not care about the type of collection, all I want is a faster way for getting my items (and executing them) than:

mIdleChoreList.Where(x => Timing.IsTimeOutByTicksNow(x.AddTime, x.WaitTime));

Because a .Where() operation is really slow.

Vincent
  • 1,497
  • 1
  • 21
  • 44
  • 1
    Sounds like a great place for a [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree)! – itsme86 Sep 19 '16 at 15:32
  • What is `mIdleChoreList`? Something that is already ordered? – Ivan Stoev Sep 19 '16 at 15:38
  • I mean, it's not clear from the question if you are looking for a data structure (in which case we need to consider also add/remove operations), or you already have one (ordered) and just looking for an effective search. – Ivan Stoev Sep 19 '16 at 15:44
  • @IvanStoev Well if i need a special data structure for it then I don't mind, i'm not currently using a specific data structure, i have tried a normal list, a concurrent queue, a dictionary (dictionary is pretty useless since there is no unique key for me to use) and the latest i'm using is the sorted priority queue from the example. The mIdleChoreList was a normal List<> which wasn't ordered. I expect ordering a List, or well anything really, takes a lot of time. – Vincent Sep 19 '16 at 17:18
  • See the marked duplicate for various options regarding search. The answers describing binary searches are most appropriate here, because you are looking not for a specific element, but for a specific position in the collection based on a value. – Peter Duniho Sep 19 '16 at 17:52

2 Answers2

1

Consider the doubly linked list (sorted list in c#), where you would insert items based off the timevalues. The items to process will be the first item in the list. Simplify remove the item if you need to process it, process it, increment the time value and add the new time value back to the list. Since the list is sorted, the item will be placed into the proper spot. The most overhead will occur on inserts.

Here's more info on linked lists in c# https://msdn.microsoft.com/en-us/library/ms132319(v=vs.110).aspx You can utilize custom comparers if you want to add custom classes to the list. e.g. Create a class with properties, TimeToExecute and IncrementValue, and insert based on TimeToExecute.

You can also explore the binary search tree (sorted dictionary in c#). The difference between the sorted dictionary and sorted list is that inserts are faster in the sorted dictionary. However, tracking/finding items to process will be slower. (you can use linq's where clause, but performance will not be the fastest).

A hashmap will have the benefit of faster inserts, but like the sorted dictionary, you will need to look for the values to process.

Please remember, dictionaries/hashmaps work best if you know exactly what you are looking for, i.e. a specific time. If you are looking for a range, you'll still need to scan the entire dictionary.

Paul Tsai
  • 893
  • 6
  • 16
  • Well that's the thing, the time stamp for when it needs to be executed won't necessarly be the oldes when i add it. For example the Fifo can have 4 values already 1 minute, 3 minutes, 5 minutes 8 minutes but now I have a new item which needs to be executed after 4 minutes. so i can't easilly put it in a regular fifo. (hence the sorted priority queue). But then again it does not have to be sorted as long as there is a fast way of getting all the values which have expired (so the data structure doesn't matter to me). would a has-map be fastest? – Vincent Sep 19 '16 at 17:20
0

For sorted list the fastest way to find any item is binary search (O(log n)).

Note: it sounds like you need list of items prior particular point (which is O(n) by itself) in theory any algorithm would do, including basic Where(x => ChekcTime(x)).

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • 1
    Binary search would be nice but i don't know the object i'm looking for (binary search for a List requires the object T in the first place. – Vincent Sep 20 '16 at 07:04