public bool Equals(GroupByState <V> that) { if (this.elements.Count != that.elements.Count) { return(false); } for (int i = 0; i < elements.Count; i++) { if (!elements.Array[i].Equals(that.elements.Array[i])) { return(false); } } return(true); }
protected override GroupByState <V> UpdateState(K key, GroupByState <V> state, int updateRootIndex) { if (state.elements.Array == null) { state.elements = new ResizeableSubArray <Weighted <V> >(0); } updateAccumulator.Clear(); resultAccumulator.Clear(); // first determine and subtract the previous outputs groupContent.Clear(); for (int i = 0; i < state.elements.Count; i++) { // set the weight associated with this record updateAccumulator[state.elements.Array[i].record] = state.elements.Array[i].weight; // add the element to the materialized list groupContent.Add(state.elements.Array[i].record); var weight = (state.elements.Array[i].weight - (i == state.elements.Count - 1 ? 0 : state.elements.Array[i + 1].weight)) / 2; if (weight != 0) { var result = resultSelector(key, groupContent); if (!resultAccumulator.ContainsKey(result)) { resultAccumulator.Add(result, 0); } resultAccumulator[result] -= weight; } } // update the accumulation based on the updates we see. for (int index = updateRootIndex; index >= 0; index = updateChain[index].previous) { var selected = selector(updateChain[index].update.record); if (!updateAccumulator.ContainsKey(selected)) { updateAccumulator.Add(selected, 0); } updateAccumulator[selected] += updateChain[index].update.weight; } // load the new accumulation into state state.elements.Clear(); foreach (var pair in updateAccumulator.OrderByDescending(x => x.Value)) { if (pair.Value > 0) { state.elements.Add(new Weighted <V>(pair.Key, pair.Value)); } if (pair.Value < 0) { Console.Error.WriteLine("Negative accumulation in GroupBy; probably a bug somewhere"); } } // second determine and add the current outputs groupContent.Clear(); for (int i = 0; i < state.elements.Count; i++) { // add the element to the materialized list groupContent.Add(state.elements.Array[i].record); var weight = (state.elements.Array[i].weight - (i == state.elements.Count - 1 ? 0 : state.elements.Array[i + 1].weight)) / 2; if (weight != 0) { var result = resultSelector(key, groupContent); if (!resultAccumulator.ContainsKey(result)) { resultAccumulator.Add(result, 0); } // subtract half the difference to the next weight, with zero for the last weight resultAccumulator[result] += weight; } } foreach (var pair in resultAccumulator) { if (pair.Value != 0) { Send(new Weighted <R>(pair.Key, pair.Value)); } } return(state); }