I fetch a bunch of categories for a dropdow tree, and have to implement search in this dropdown. If there is a match in one of the elements, it should also get all parents to display in the dropdown hierarchy.
I started with 2 foreach
loops where I filtered out the matches, and one where I check the matches for parentId
and recursive add the parents untill there are none left ( parentId == 0
).
public ScrapCategory[] Filter(ScrapCategory[] categories, string searchString)
{
var result = new List<ScrapCategory>();
foreach (ScrapCategory category in categories)
{
if (category.Description.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
result.Add(category);
if (category.ParentId == 0)
continue;
ScrapCategory currentParent = categories.Where(x => x.Id == category.ParentId).First();
if (!result.Contains(currentParent))
result.Add(currentParent);
while (currentParent?.ParentId > 0)
{
currentParent = categories.Where(x => x.Id == currentParent.ParentId)?.First();
if (!result.Contains(currentParent))
result.Add(currentParent);
}
}
return result.OrderBy(x => x.Level).ToArray();
}
I get the expected result but I would love to see this in O(N), so only one interation over the categories
without those .Where()
clauses.
Edit: I managed to get rid of one .Where()
clause.
public ScrapCategory[] Filter(ScrapCategory[] categories, string searchString)
{
var result = new List<ScrapCategory>();
foreach (ScrapCategory category in categories)
{
if (category.Description.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
result.Add(category);
if (category.ParentId > 0)
{
int parentId = category.ParentId;
while (parentId > 0)
{
var parent = categories.Where(x => x.Id == parentId)?.First();
if (!result.Contains(parent))
result.Add(parent);
parentId = parent.ParentId;
}
}
}
return result.OrderBy(x => x.Level).ToArray();
}
This is my final result, and I'm happy with it.
public ScrapCategory[] Filter(ScrapCategory[] categories, string searchString)
{
var lookup = categories.ToDictionary(category => category.Id);
var result = new HashSet<ScrapCategory>();
foreach (ScrapCategory category in categories)
{
if (category.Description.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
result.Add(category);
int parentId = category.ParentId;
while (parentId > 0)
{
ScrapCategory parent = lookup[parentId];
if (!result.Add(parent))
break;
parentId = parent.ParentId;
}
}
return result.OrderBy(n => n.Level).ToArray();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.