/// <summary> /// Moves unique entries to the front of the list. /// </summary> private int MoveUniqueEntriesToFront(List <OrderByPropertyEntry> sortedData, OrderByPropertyComparer comparer) { // If we have sorted data then we know we have at least one unique item int uniqueCount = sortedData.Count > 0 ? 1 : 0; // Move the first of each unique entry to the front of the list for (int uniqueItemIndex = 0, nextUniqueItemIndex = 1; uniqueItemIndex < sortedData.Count && uniqueCount != Top; uniqueItemIndex++, nextUniqueItemIndex++) { // Identify the index of the next unique item while (nextUniqueItemIndex < sortedData.Count && comparer.Compare(sortedData[uniqueItemIndex], sortedData[nextUniqueItemIndex]) == 0) { nextUniqueItemIndex++; } // If there are no more unique items, break if (nextUniqueItemIndex == sortedData.Count) { break; } // Move the next unique item forward and increment the unique item counter sortedData[uniqueItemIndex + 1] = sortedData[nextUniqueItemIndex]; uniqueCount++; } return(uniqueCount); }
private static int FindInObjectGroups(List <GroupInfo> groups, OrderByPropertyEntry target, OrderByPropertyComparer comparer) { for (int i = 0; i < groups.Count; i++) { if (comparer.Compare(groups[i].GroupValue, target) == 0) { return(i); } } return(-1); }
/// <summary> /// Utility function called by Group-Object to create Groups. /// </summary> /// <param name="currentObjectEntry">Input object that needs to be grouped.</param> /// <param name="noElement">True if we are not accumulating objects.</param> /// <param name="groups">List containing Groups.</param> /// <param name="groupInfoDictionary">Dictionary used to keep track of the groups with hash of the property values being the key.</param> /// <param name="orderByPropertyComparer">The Comparer to be used while comparing to check if new group has to be created.</param> private static void DoOrderedGrouping( OrderByPropertyEntry currentObjectEntry, bool noElement, List <GroupInfo> groups, Dictionary <object, GroupInfo> groupInfoDictionary, OrderByPropertyComparer orderByPropertyComparer) { var currentObjectOrderValues = currentObjectEntry.orderValues; if (currentObjectOrderValues != null && currentObjectOrderValues.Count > 0) { object currentTupleObject = PSTuple.ArrayToTuple(currentObjectOrderValues); if (groupInfoDictionary.TryGetValue(currentTupleObject, out var currentGroupInfo)) { // add this inputObject to an existing group currentGroupInfo.Add(currentObjectEntry.inputObject); } else { bool isCurrentItemGrouped = false; if (groups.Count > 0) { var lastGroup = groups[groups.Count - 1]; // Check if the current input object can be converted to one of the already known types // by looking up in the type to GroupInfo mapping. if (orderByPropertyComparer.Compare(lastGroup.GroupValue, currentObjectEntry) == 0) { lastGroup.Add(currentObjectEntry.inputObject); isCurrentItemGrouped = true; } } if (!isCurrentItemGrouped) { // create a new group s_tracer.WriteLine("Create a new group: {0}", currentObjectOrderValues); GroupInfo newObjGrp = noElement ? new GroupInfoNoElement(currentObjectEntry) : new GroupInfo(currentObjectEntry); groups.Add(newObjGrp); groupInfoDictionary.Add(currentTupleObject, newObjGrp); } } } }
/// <summary> /// Utility function called by Group-Object to create Groups. /// </summary> /// <param name="currentObjectEntry">Input object that needs to be grouped.</param> /// <param name="noElement">true if we are not accumulating objects</param> /// <param name="groups">List containing Groups.</param> /// <param name="groupInfoDictionary">Dictionary used to keep track of the groups with hash of the property values being the key.</param> /// <param name="orderByPropertyComparer">The Comparer to be used while comparing to check if new group has to be created.</param> internal static void DoGrouping(OrderByPropertyEntry currentObjectEntry, bool noElement, List <GroupInfo> groups, Dictionary <object, GroupInfo> groupInfoDictionary, OrderByPropertyComparer orderByPropertyComparer) { if (currentObjectEntry != null && currentObjectEntry.orderValues != null && currentObjectEntry.orderValues.Count > 0) { object currentTupleObject = PSTuple.ArrayToTuple(currentObjectEntry.orderValues.ToArray()); GroupInfo currentGroupInfo = null; if (groupInfoDictionary.TryGetValue(currentTupleObject, out currentGroupInfo)) { if (currentGroupInfo != null) { //add this inputObject to an existing group currentGroupInfo.Add(currentObjectEntry.inputObject); } } else { bool isCurrentItemGrouped = false; for (int groupsIndex = 0; groupsIndex < groups.Count; groupsIndex++) { // Check if the current input object can be converted to one of the already known types // by looking up in the type to GroupInfo mapping. if (orderByPropertyComparer.Compare(groups[groupsIndex].GroupValue, currentObjectEntry) == 0) { groups[groupsIndex].Add(currentObjectEntry.inputObject); isCurrentItemGrouped = true; break; } } if (!isCurrentItemGrouped) { // create a new group s_tracer.WriteLine("Create a new group: {0}", currentObjectEntry.orderValues); GroupInfo newObjGrp = noElement ? new GroupInfoNoElement(currentObjectEntry) : new GroupInfo(currentObjectEntry); groups.Add(newObjGrp); groupInfoDictionary.Add(currentTupleObject, newObjGrp); } } } }
/// <summary> /// The following is the matching algorithm: /// Retrieve the incoming object (differenceEntry) if any /// Retrieve the next reference object (referenceEntry) if any /// If differenceEntry matches referenceEntry /// Emit referenceEntry as a match /// Return /// If differenceEntry matches any entry in referenceEntryBacklog /// Emit the backlog entry as a match /// Remove the backlog entry from referenceEntryBacklog /// Clear differenceEntry /// If referenceEntry (if any) matches any entry in differenceEntryBacklog /// Emit referenceEntry as a match /// Remove the backlog entry from differenceEntryBacklog /// Clear referenceEntry /// If differenceEntry is still present /// If SyncWindow is 0 /// Emit differenceEntry as unmatched /// Else /// While there is no space in differenceEntryBacklog /// Emit oldest entry in differenceEntryBacklog as unmatched /// Remove oldest entry from differenceEntryBacklog /// Add differenceEntry to differenceEntryBacklog /// If referenceEntry is still present /// If SyncWindow is 0 /// Emit referenceEntry as unmatched /// Else /// While there is no space in referenceEntryBacklog /// Emit oldest entry in referenceEntryBacklog as unmatched /// Remove oldest entry from referenceEntryBacklog /// Add referenceEntry to referenceEntryBacklog. /// </summary> /// <param name="differenceEntry"></param> private void Process(OrderByPropertyEntry differenceEntry) { Diagnostics.Assert(_referenceEntries != null, "null referenceEntries"); // Retrieve the next reference object (referenceEntry) if any OrderByPropertyEntry referenceEntry = null; if (_referenceObjectIndex < _referenceEntries.Count) { referenceEntry = _referenceEntries[_referenceObjectIndex++]; } // If differenceEntry matches referenceEntry // Emit referenceEntry as a match // Return // 2005/07/19 Switched order of referenceEntry and differenceEntry // so that we cast differenceEntry to the type of referenceEntry. if (referenceEntry != null && differenceEntry != null && 0 == _comparer.Compare(referenceEntry, differenceEntry)) { EmitMatch(referenceEntry); return; } // If differenceEntry matches any entry in referenceEntryBacklog // Emit the backlog entry as a match // Remove the backlog entry from referenceEntryBacklog // Clear differenceEntry OrderByPropertyEntry matchingEntry = MatchAndRemove(differenceEntry, _referenceEntryBacklog); if (matchingEntry != null) { EmitMatch(matchingEntry); differenceEntry = null; } // If referenceEntry (if any) matches any entry in differenceEntryBacklog // Emit referenceEntry as a match // Remove the backlog entry from differenceEntryBacklog // Clear referenceEntry matchingEntry = MatchAndRemove(referenceEntry, _differenceEntryBacklog); if (matchingEntry != null) { EmitMatch(referenceEntry); referenceEntry = null; } // If differenceEntry is still present // If SyncWindow is 0 // Emit differenceEntry as unmatched // Else // While there is no space in differenceEntryBacklog // Emit oldest entry in differenceEntryBacklog as unmatched // Remove oldest entry from differenceEntryBacklog // Add differenceEntry to differenceEntryBacklog if (differenceEntry != null) { if (0 < SyncWindow) { while (_differenceEntryBacklog.Count >= SyncWindow) { EmitDifferenceOnly(_differenceEntryBacklog[0]); _differenceEntryBacklog.RemoveAt(0); } _differenceEntryBacklog.Add(differenceEntry); } else { EmitDifferenceOnly(differenceEntry); } } // If referenceEntry is still present // If SyncWindow is 0 // Emit referenceEntry as unmatched // Else // While there is no space in referenceEntryBacklog // Emit oldest entry in referenceEntryBacklog as unmatched // Remove oldest entry from referenceEntryBacklog // Add referenceEntry to referenceEntryBacklog if (referenceEntry != null) { if (0 < SyncWindow) { while (_referenceEntryBacklog.Count >= SyncWindow) { EmitReferenceOnly(_referenceEntryBacklog[0]); _referenceEntryBacklog.RemoveAt(0); } _referenceEntryBacklog.Add(referenceEntry); } else { EmitReferenceOnly(referenceEntry); } } }