github.com/blend/go-sdk@v1.20220411.3/collections/linked_list.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package collections
     9  
    10  type listNode struct {
    11  	Next     *listNode
    12  	Previous *listNode
    13  	Value    interface{}
    14  }
    15  
    16  // NewLinkedList returns a new linked list instance.
    17  func NewLinkedList() *LinkedList {
    18  	return &LinkedList{}
    19  }
    20  
    21  // NewLinkedListFromValues creates a linked list out of a slice.
    22  func NewLinkedListFromValues(values []interface{}) *LinkedList {
    23  	list := new(LinkedList)
    24  	for _, v := range values {
    25  		list.Enqueue(v)
    26  	}
    27  	return list
    28  }
    29  
    30  // LinkedList is an implementation of a fifo buffer using nodes and poitners.
    31  // Remarks; it is not threadsafe. It is constant(ish) time in all ops.
    32  type LinkedList struct {
    33  	head   *listNode
    34  	tail   *listNode
    35  	length int
    36  }
    37  
    38  // Len returns the length of the queue in constant time.
    39  func (q *LinkedList) Len() int {
    40  	return q.length
    41  }
    42  
    43  // Enqueue adds a new value to the queue.
    44  func (q *LinkedList) Enqueue(value interface{}) {
    45  	node := &listNode{Value: value}
    46  
    47  	if q.head == nil { //the queue is empty, that is to say head is nil
    48  		q.head = node
    49  		q.tail = node
    50  	} else { //the queue is not empty, we have a (valid) tail pointer
    51  		q.tail.Previous = node
    52  		node.Next = q.tail
    53  		q.tail = node
    54  	}
    55  
    56  	q.length++
    57  }
    58  
    59  // Dequeue removes an item from the front of the queue and returns it.
    60  func (q *LinkedList) Dequeue() interface{} {
    61  	if q.head == nil {
    62  		return nil
    63  	}
    64  
    65  	headValue := q.head.Value
    66  
    67  	if q.length == 1 && q.head == q.tail {
    68  		q.head = nil
    69  		q.tail = nil
    70  	} else {
    71  		q.head = q.head.Previous
    72  		if q.head != nil {
    73  			q.head.Next = nil
    74  		}
    75  	}
    76  
    77  	q.length--
    78  	return headValue
    79  }
    80  
    81  // DequeueBack pops the _last_ element off the linked list.
    82  func (q *LinkedList) DequeueBack() interface{} {
    83  	if q.tail == nil {
    84  		return nil
    85  	}
    86  	tailValue := q.tail.Value
    87  
    88  	if q.length == 1 {
    89  		q.head = nil
    90  		q.tail = nil
    91  	} else {
    92  		q.tail = q.tail.Next
    93  		if q.tail != nil {
    94  			q.tail.Previous = nil
    95  		}
    96  	}
    97  
    98  	q.length--
    99  	return tailValue
   100  }
   101  
   102  // Peek returns the first element of the queue but does not remove it.
   103  func (q *LinkedList) Peek() interface{} {
   104  	if q.head == nil {
   105  		return nil
   106  	}
   107  	return q.head.Value
   108  }
   109  
   110  // PeekBack returns the last element of the queue.
   111  func (q *LinkedList) PeekBack() interface{} {
   112  	if q.tail == nil {
   113  		return nil
   114  	}
   115  	return q.tail.Value
   116  }
   117  
   118  // Clear clears the linked list.
   119  func (q *LinkedList) Clear() {
   120  	q.tail = nil
   121  	q.head = nil
   122  	q.length = 0
   123  }
   124  
   125  // Drain calls the consumer for each element of the linked list.
   126  func (q *LinkedList) Drain() []interface{} {
   127  	if q.head == nil {
   128  		return nil
   129  	}
   130  
   131  	contents := make([]interface{}, q.length)
   132  	nodePtr := q.head
   133  	var index int
   134  	for nodePtr != nil {
   135  		contents[index] = nodePtr.Value
   136  		nodePtr = nodePtr.Previous
   137  		index++
   138  	}
   139  	q.tail = nil
   140  	q.head = nil
   141  	q.length = 0
   142  	return contents
   143  }
   144  
   145  // Each calls the consumer for each element of the linked list.
   146  func (q *LinkedList) Each(consumer func(value interface{})) {
   147  	if q.head == nil {
   148  		return
   149  	}
   150  
   151  	nodePtr := q.head
   152  	for nodePtr != nil {
   153  		consumer(nodePtr.Value)
   154  		nodePtr = nodePtr.Previous
   155  	}
   156  }
   157  
   158  // Consume calls the consumer for each element of the linked list, removing it.
   159  func (q *LinkedList) Consume(consumer func(value interface{})) {
   160  	if q.head == nil {
   161  		return
   162  	}
   163  
   164  	nodePtr := q.head
   165  	for nodePtr != nil {
   166  		consumer(nodePtr.Value)
   167  		nodePtr = nodePtr.Previous
   168  	}
   169  	q.tail = nil
   170  	q.head = nil
   171  	q.length = 0
   172  }
   173  
   174  // EachUntil calls the consumer for each element of the linked list, but can abort.
   175  func (q *LinkedList) EachUntil(consumer func(value interface{}) bool) {
   176  	if q.head == nil {
   177  		return
   178  	}
   179  
   180  	nodePtr := q.head
   181  	for nodePtr != nil {
   182  		if !consumer(nodePtr.Value) {
   183  			return
   184  		}
   185  		nodePtr = nodePtr.Previous
   186  	}
   187  }
   188  
   189  // ReverseEachUntil calls the consumer for each element of the linked list, but can abort.
   190  func (q *LinkedList) ReverseEachUntil(consumer func(value interface{}) bool) {
   191  	if q.head == nil {
   192  		return
   193  	}
   194  
   195  	nodePtr := q.tail
   196  	for nodePtr != nil {
   197  		if !consumer(nodePtr.Value) {
   198  			return
   199  		}
   200  		nodePtr = nodePtr.Next
   201  	}
   202  }
   203  
   204  // Contents returns the full contents of the queue as a slice.
   205  func (q *LinkedList) Contents() []interface{} {
   206  	if q.head == nil {
   207  		return []interface{}{}
   208  	}
   209  
   210  	values := []interface{}{}
   211  	nodePtr := q.head
   212  	for nodePtr != nil {
   213  		values = append(values, nodePtr.Value)
   214  		nodePtr = nodePtr.Previous
   215  	}
   216  	return values
   217  }