/// <summary> /// Releases the lookup and any key and/or value nodes it contains to their respective pools. /// </summary> public void Dispose() { var valuesAcc = new LinkedHeadTail <T>(); var runner = keys.head; while (runner != null) { valuesAcc.Append(RemoveValues(runner.value)); runner = runner.next; } if (dictionary.Count > 0) { SmoothLogger.LogWarning("Lookup had dictionary keys that were not in the key list."); foreach (var values in dictionary.Values) { valuesAcc.Append(values); } dictionary.Clear(); } keys.Dispose(); valuesAcc.Dispose(); lock (pool) { pool.Push(this); } }
/// <summary> /// Appends the specified list to the value list for the specified key. If the key was previously unmapped it is appended to the key list. /// Calling this method transfers ownership of the nodes in the specified list to the lookup. /// </summary> public void Add(K key, LinkedHeadTail <T> values) { LinkedHeadTail <T> existing; if (dictionary.TryGetValue(key, out existing)) { existing.Append(values); dictionary[key] = existing; } else { keys.Append(key); dictionary[key] = values; } }
/// <summary> /// Returns a list of all the values contained in this lookup and adds the lookup to the disposal queue. /// Items in the list will be ordered based on the ordering of the key list, then by the position within value list for the item's key. /// Ownership of the returned nodes is transferred to the caller, who is responsible for their disposal. /// </summary> public LinkedHeadTail <T> FlattenAndDispose() { var values = new LinkedHeadTail <T>(); var runner = keys.head; while (runner != null) { values.Append(RemoveValues(runner.value)); runner = runner.next; } keys.DisposeInBackground(); DisposeInBackground(); return(values); }
/// <summary> /// Appends the specified list to the end of this list. /// This list and the specified list must be well formed when calling this method or the program will enter an invalid state, resulting in /// unspecified behaviour. /// Calling this method will invalidate the specified list and any variables containing its nodes. /// </summary> public void Append(LinkedHeadTail <T> other) { if (other.count == 0) { // noop } else if (head == null) { head = other.head; tail = other.tail; count = other.count; } else { tail.next = other.head; tail = other.tail; count += other.count; } }
/// <summary> /// Returns a grouping for the specified key and values. /// </summary> public Grouping(K key, LinkedHeadTail <T> values) { this.key = key; this.values = values; }
private Lookup(IEqualityComparer <K> comparer) { dictionary = new Dictionary <K, LinkedHeadTail <T> >(comparer); keys = new LinkedHeadTail <K>(); }
/// <summary> /// Sorts the lookup's keys using the specified comparison and ordering. /// This method uses an introspective merge sort algorithm that will optimally sort rather than split lists with 3 or fewer nodes. /// </summary> public Lookup <K, T> SortKeys(Comparison <K> comparison, bool ascending) { keys = Linked.Sort(keys, comparison, ascending); return(this); }
public bool Equals(LinkedHeadTail <T> other) { return(head == other.head); }