//--------------------------------------------------------------------------------------- // MoveNext will invoke the entire query sub-tree, accumulating results into a hash- // table, upon the first call. Then for the first call and all subsequent calls, we will // just enumerate the key-set from the hash-table, retrieving groupings of key-elements. // internal override bool MoveNext(ref IGrouping <TGroupKey, TElement> currentElement, ref TOrderKey currentKey) { Debug.Assert(_source != null); Debug.Assert(_keySelector != null); // Lazy-init the mutable state. This also means we haven't yet built our lookup of // groupings, so we can go ahead and do that too. Mutables mutables = _mutables; if (mutables == null) { mutables = _mutables = new Mutables(); // Build the hash lookup and start enumerating the lookup at the beginning. mutables._hashLookup = BuildHashLookup(); Debug.Assert(mutables._hashLookup != null); mutables._hashLookupIndex = -1; } // Now, with a hash lookup in hand, we just enumerate the keys. So long // as the key-value lookup has elements, we have elements. if (++mutables._hashLookupIndex < mutables._hashLookup.Count) { GroupKeyData value = mutables._hashLookup[mutables._hashLookupIndex].Value; currentElement = value._grouping; currentKey = value._orderKey; return(true); } return(false); }
//----------------------------------------------------------------------------------- // Builds the hash lookup, transforming from TSource to TElement through whatever means is appropriate. // protected override HashLookup <Wrapper <TGroupKey>, GroupKeyData> BuildHashLookup() { HashLookup <Wrapper <TGroupKey>, GroupKeyData> hashLookup = new HashLookup <Wrapper <TGroupKey>, GroupKeyData>( new WrapperEqualityComparer <TGroupKey>(_keyComparer)); Pair <TSource, TGroupKey> sourceElement = default(Pair <TSource, TGroupKey>); TOrderKey sourceOrderKey = default(TOrderKey) !; int i = 0; while (_source.MoveNext(ref sourceElement, ref sourceOrderKey)) { if ((i++ & CancellationState.POLL_INTERVAL) == 0) { _cancellationToken.ThrowIfCancellationRequested(); } ; // Generate a key and place it into the hashtable. Wrapper <TGroupKey> key = new Wrapper <TGroupKey>(sourceElement.Second); // If the key already exists, we just append it to the existing list -- // otherwise we will create a new one and add it to that instead. GroupKeyData?currentValue = null; if (hashLookup.TryGetValue(key, ref currentValue)) { if (_orderComparer.Compare(sourceOrderKey, currentValue._orderKey) < 0) { currentValue._orderKey = sourceOrderKey; } } else { currentValue = new GroupKeyData(sourceOrderKey, key.Value, _orderComparer); hashLookup.Add(key, currentValue); } Debug.Assert(currentValue != null); // Call to the base class to yield the current value. currentValue._grouping.Add(_elementSelector(sourceElement.First), sourceOrderKey); } // Sort the elements within each group for (int j = 0; j < hashLookup.Count; j++) { hashLookup[j].Value._grouping.DoneAdding(); } return(hashLookup); }
internal override bool MoveNext(ref IGrouping <TGroupKey, TElement> currentElement, ref TOrderKey currentKey) { Mutables <TSource, TGroupKey, TElement, TOrderKey> mutables = this.m_mutables; if (mutables == null) { mutables = this.m_mutables = new Mutables <TSource, TGroupKey, TElement, TOrderKey>(); mutables.m_hashLookup = this.BuildHashLookup(); mutables.m_hashLookupIndex = -1; } if (++mutables.m_hashLookupIndex < mutables.m_hashLookup.Count) { KeyValuePair <Wrapper <TGroupKey>, GroupKeyData <TSource, TGroupKey, TElement, TOrderKey> > pair = mutables.m_hashLookup[mutables.m_hashLookupIndex]; GroupKeyData <TSource, TGroupKey, TElement, TOrderKey> data = pair.Value; currentElement = data.m_grouping; currentKey = data.m_orderKey; return(true); } return(false); }
public bool Add(THashKey hashKey, TElement element, TOrderKey orderKey) { bool hasCollision = true; GroupKeyData?currentValue = default(GroupKeyData); if (!_base.TryGetValue(hashKey, ref currentValue)) { currentValue = new GroupKeyData(orderKey, hashKey, _orderKeyComparer); _base.Add(hashKey, currentValue); hasCollision = false; } currentValue._grouping.Add(element, orderKey); if (_orderKeyComparer.Compare(orderKey, currentValue._orderKey) < 0) { currentValue._orderKey = orderKey; } return(hasCollision); }
protected override Pair <IEnumerable <TElement>, Pair <bool, TOrderKey> > CreateValuePair(GroupKeyData baseValue) { return(new Pair <IEnumerable <TElement>, Pair <bool, TOrderKey> >(baseValue._grouping, Wrap(baseValue._orderKey))); }