2 people like it.

Simple queue that allows for removing items anywhere as well as FIFO operation.

A simple queue that also allows for the removal of items waiting in the queue as well as FIFO operation. This is useful if for example you have a queue of items that might need to expire at different times if they have been waiting in the queue for too long.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
open System
open System.Collections.Generic

/// A simple queue that also allows for the removal of items waiting in the queue as well as FIFO operation.
type FilterableQueue<'a> () =
    let queue = new LinkedList<'a>()

    /// Add an item to the tail of the queue.
    member x.Enqueue (item: 'a) = queue.AddLast item |> ignore

    /// Get the item at the head of the queue and remove it, the result is None if the queue is empty.
    member x.TryDequeue () =
        match x.Count with
        | 0 -> None
        | _ -> let item = queue.First.Value
               queue.RemoveFirst ()
               Some item

    /// The number of items currently in the queue.
    member x.Count with get () = queue.Count

    /// Remove items from the queue for which the predicate is true.
    member x.RemoveSelectedItems predicate =
        // A list that will contain any items removed from the queue.
        let removedItems = new LinkedList<_>()

        // Tail-recursive function to iterate over the nodes in the queue.
        let rec loop (node: LinkedListNode<'a>) =
            match predicate node.Value with
            | true ->
                // Predicate returned true, so remove the item from the queue and add it to the removedItems list.
                let next = node.Next
                removedItems.AddLast node.Value |> ignore
                queue.Remove node
                next
            | false ->
                // Item should not be removed if predicate returns false, just move onto the next element in the queue.
                node.Next
            |> function
               // Either there is another node to process or not..
               | null -> ()
               | nextNode -> loop nextNode
        // Start the scan of the nodes if there are any.
        if queue.Count <> 0 then loop queue.First
        // Evaluates to the list of items that were removed.
        removedItems


// Example..
let q = FilterableQueue<int>()

q.Enqueue 3
q.Enqueue 7
q.Enqueue 9

// Filter anything where 8 is less then or equal to the item.
let removed = q.RemoveSelectedItems ((<=) 8)

let a = q.TryDequeue () // Some 3
let b = q.TryDequeue () // Some 7
let c = q.TryDequeue () // None
namespace System
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type FilterableQueue<'a> =
  new : unit -> FilterableQueue<'a>
  member Enqueue : item:'a -> unit
  member RemoveSelectedItems : predicate:('a -> bool) -> LinkedList<'a>
  member TryDequeue : unit -> 'a option
  member Count : int

Full name: Script.FilterableQueue<_>


 A simple queue that also allows for the removal of items waiting in the queue as well as FIFO operation.


--------------------
new : unit -> FilterableQueue<'a>
val queue : LinkedList<'a>
Multiple items
type LinkedList<'T> =
  new : unit -> LinkedList<'T> + 1 overload
  member AddAfter : node:LinkedListNode<'T> * value:'T -> LinkedListNode<'T> + 1 overload
  member AddBefore : node:LinkedListNode<'T> * value:'T -> LinkedListNode<'T> + 1 overload
  member AddFirst : value:'T -> LinkedListNode<'T> + 1 overload
  member AddLast : value:'T -> LinkedListNode<'T> + 1 overload
  member Clear : unit -> unit
  member Contains : value:'T -> bool
  member CopyTo : array:'T[] * index:int -> unit
  member Count : int
  member Find : value:'T -> LinkedListNode<'T>
  ...
  nested type Enumerator

Full name: System.Collections.Generic.LinkedList<_>

--------------------
LinkedList() : unit
LinkedList(collection: IEnumerable<'T>) : unit
val x : FilterableQueue<'a>
member FilterableQueue.Enqueue : item:'a -> unit

Full name: Script.FilterableQueue`1.Enqueue


 Add an item to the tail of the queue.
val item : 'a
LinkedList.AddLast(node: LinkedListNode<'a>) : unit
LinkedList.AddLast(value: 'a) : LinkedListNode<'a>
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
member FilterableQueue.TryDequeue : unit -> 'a option

Full name: Script.FilterableQueue`1.TryDequeue


 Get the item at the head of the queue and remove it, the result is None if the queue is empty.
property FilterableQueue.Count: int


 The number of items currently in the queue.
union case Option.None: Option<'T>
property LinkedList.First: LinkedListNode<'a>
property LinkedListNode.Value: 'a
LinkedList.RemoveFirst() : unit
union case Option.Some: Value: 'T -> Option<'T>
member FilterableQueue.Count : int

Full name: Script.FilterableQueue`1.Count


 The number of items currently in the queue.
property LinkedList.Count: int
member FilterableQueue.RemoveSelectedItems : predicate:('a -> bool) -> LinkedList<'a>

Full name: Script.FilterableQueue`1.RemoveSelectedItems


 Remove items from the queue for which the predicate is true.
val predicate : ('a -> bool)
val removedItems : LinkedList<'a>
val loop : (LinkedListNode<'a> -> unit)
val node : LinkedListNode<'a>
Multiple items
type LinkedListNode<'T> =
  new : value:'T -> LinkedListNode<'T>
  member List : LinkedList<'T>
  member Next : LinkedListNode<'T>
  member Previous : LinkedListNode<'T>
  member Value : 'T with get, set

Full name: System.Collections.Generic.LinkedListNode<_>

--------------------
LinkedListNode(value: 'T) : unit
val next : LinkedListNode<'a>
property LinkedListNode.Next: LinkedListNode<'a>
LinkedList.Remove(node: LinkedListNode<'a>) : unit
LinkedList.Remove(value: 'a) : bool
val nextNode : LinkedListNode<'a>
val q : FilterableQueue<int>

Full name: Script.q
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
member FilterableQueue.Enqueue : item:'a -> unit


 Add an item to the tail of the queue.
val removed : LinkedList<int>

Full name: Script.removed
member FilterableQueue.RemoveSelectedItems : predicate:('a -> bool) -> LinkedList<'a>


 Remove items from the queue for which the predicate is true.
val a : int option

Full name: Script.a
member FilterableQueue.TryDequeue : unit -> 'a option


 Get the item at the head of the queue and remove it, the result is None if the queue is empty.
val b : int option

Full name: Script.b
val c : int option

Full name: Script.c
Raw view Test code New version

More information

Link:http://fssnip.net/7OC
Posted:8 years ago
Author:David Neale
Tags: queue