I am currently looking into improving code efficiency while working with a flat string collection in C#. The strings in this collection can be considered a "group" or a "child".
The problem is that the API for this collection is exposed in such a way that the type of each String in the collection is not directly retrievable and must be determined through other properties.
An example collection:
[0] Group Item
[1] Child Item
[2] Child Item
[3] Child Item
[4] Child Item
[5] Group Item
[6] Child Item
[7] Child Item
[8] Group Item
[9] Child Item
[10] Child Item
[11] Child Item
For the collection the following is true:
- Position 0 is always a group item
- There can be 0 to N child items between two group items
- The content of the string does not indicate if a string is a child or a group
The following data is available to determine group/child types:
- ItemCount (The total amount of strings in the collection)
- GroupCount (The total amount of group strings in the collection)
- GetChildCount(int groupIndex) (The amount of child items after the group with groupIndex before the next group item)
The data I need to determine is:
Group position (The position of a group item based on its zero based index. For example: The group index of 2 should return position 8 from the example collection)
Child position (The position of a child item based on its zero based group index and child index. For example: The group index of 0 and child index of 3 should return position 4 from the example collection, and a group index of 2 and a child index of 0 should return position 9)
The reverse of the above (The indexes for the positions)
Currently I have created up the following methods to determine these values:
public bool IsGroupPosition(int position)
{
int currPosition = 0;
for(int i = 0;i < GroupCount;i++)
{
if(currPosition < position)
{
currPosition = currPosition + (GetChildrenCount(i) + 1); //Go to next group item in collection
continue;
}
else if(currPosition > position)
{
return false; //We passed the position, this is no group item
}
else
{
return true; //The position is equal to a group position
}
}
return false;
}
public bool IsChildPosition(int position)
{
int currPosition = 0;
for (int i = 0; i < GroupCount; i++)
{
if (currPosition == position)
{
return false;
}
else if (currPosition > position)
{
return true; //We passed the position, this is a child
}
else
{
currPosition = currPosition + (GetChildrenCount(i) + 1); //Go to next group in collection
}
}
return false;
}
public int GetGroupIndexForPosition(int position)
{
int currPosition = 0;
for (int i = 0; i <= GroupCount; i++)
{
int nextGroupPos = currPosition + (GetChildrenCount(i) + 1);
if (nextGroupPos > position)
{
return i;
}
currPosition = nextGroupPos;
}
return -1;
}
public int GetChildIndexForPosition(int position)
{
int currPosition = 0;
for (int i = 0; i < GroupCount; i++)
{
int nextGroupPos = currPosition + (GetChildrenCount(i) + 1);
if (nextGroupPos > position)
{
return (position - currPosition) - 1;
}
currPosition = nextGroupPos;
}
return -1;
}
public int GetPositionForGroup(int groupIndex)
{
int position = 0;
for (int i = 0; i < groupIndex; i++)
{
position += (GetChildrenCount(i) + 1);
}
return position;
}
public int GetPositionForChild(int groupIndex, int childIndex)
{
return GetPositionForGroup(groupIndex) + childIndex;
}
It's basically enumerating through the collection by a GetChildrenCount(i) amount of steps. And while these methods seem to work fine in terms of functionality, I was wondering if I overlooked something and if there are more efficient ways to determine the group and child positions.