搜索分层列表
我有一个简单的类定义为:
public class IndexEntry
{
public bool HighScore { get; set; }
public List<IndexEntry> SubEntries { get; set; }
//Other properties, etc...
}
我现在需要搜索列表以查找其 HighScore 属性设置为 true 的一项。由于它不是一个平面列表,而是一个层次结构,其深度可能未知,并且由于我正在查找的项目可能包含在任何一个子实体列表中,因此我无法执行像这样的简单 Lambda this:
var foundHighScore = myList.FirstOrDefault(IE => IE.HighScore == true);
这是我的代码。我知道它很丑(至少对我来说是这样)。它可以工作,但是在一个甚至相当大的列表上速度很慢,我确信一定有更好的方法。
private IndexEntry GetHighScoreEntry(IEnumerable<IndexEntry> entryList)
{
IndexEntry result = null;
IndexEntry recursiveResult = null;
foreach (IndexEntry currentEntry in entryList)
{
if (currentEntry.HighScore)
{
result = currentEntry;
break; //Don't need to look anymore, we found our highscore.;
}
else
{
if ((currentEntry.SubEntries == null) || (currentEntry.SubEntries.Count < 1))
{
continue;
}
else
{
recursiveResult = GetHighScoreEntry(currentEntry.SubEntries);
if (recursiveResult == null)
continue;
result = recursiveResult;
break;
}
}
}
return result;
}
我相信有一种更好的方法,使用稍微复杂的 lambda 或 LINQ 来清理此代码并使其性能更高。
预先感谢您的帮助。
I've got a simple class defined as:
public class IndexEntry
{
public bool HighScore { get; set; }
public List<IndexEntry> SubEntries { get; set; }
//Other properties, etc...
}
I now need to search through a List to find the one item that has its HighScore Property set to true. Since it isn't a flat list, but a Hierarchy which can be an unknown number of levels deep and since the item I'm looking for might be contained in any one of the SubEnties lists, I can't do a simple Lambda like this:
var foundHighScore = myList.FirstOrDefault(IE => IE.HighScore == true);
Here's the code I have. I know it's ugly (at least it seems that way to me). It works, but is slow as sin on an even remotely large list and I'm sure there must be a better way.
private IndexEntry GetHighScoreEntry(IEnumerable<IndexEntry> entryList)
{
IndexEntry result = null;
IndexEntry recursiveResult = null;
foreach (IndexEntry currentEntry in entryList)
{
if (currentEntry.HighScore)
{
result = currentEntry;
break; //Don't need to look anymore, we found our highscore.;
}
else
{
if ((currentEntry.SubEntries == null) || (currentEntry.SubEntries.Count < 1))
{
continue;
}
else
{
recursiveResult = GetHighScoreEntry(currentEntry.SubEntries);
if (recursiveResult == null)
continue;
result = recursiveResult;
break;
}
}
}
return result;
}
I've got believe that there's a better way using a slightly more complex lambda or with LINQ to clean up this code and make it more performant.
Thanks in advance for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
到目前为止发布的所有解决方案都是专门的 - 它们不是通用的或通用的,因此,下次您拥有分层列表时,您将必须编写新的解决方案。恶心。
这是一个通用的通用解决方案,可以满足您所有的分层需求:
以下是您使用它的方法:
简单易行。
此扩展方法可用于将任何分层数据转换为平面列表,可以使用 LINQ 对其进行搜索。
该解决方案的另一个优点是它使用惰性求值,因此它只执行调用者要求的工作。例如,在上面的代码中,一旦找到 HighScore,Flatten 将停止生成项目。
该解决方案还避免了递归,这对于深度嵌套的层次结构来说可能是一项成本高昂的操作,从而避免了递归解决方案所产生的许多堆栈分配。
All the solutions posted so far are specialized - they are not generic or general, and thus, the next time you have a hierarchical list, you'll have to code up a new solution. Yuck.
Here's a general, generic solution that will work for all your hierarchical needs:
Here's how you'd use it:
Easy as cheese.
This extension method can be used to turn any hierarchical data into a flat list, which can them be searched using LINQ.
Another great thing about this solution is that is uses lazy evaluation, thus it only does as much work as the caller demands. For example, in the above code, Flatten will stop churning out items as soon as a HighScore is found.
This solution also avoids recursion, which can be a costly operation for deeply nested hierarchies, avoiding the many stack allocations that recursive solutions incur.
递归是你的朋友。
Recursion is your friend here.
您可以使用 lambda 表达式显着缩小搜索范围,例如:
Update
实际上,第一个解决方案将无法正确遍历。我不认为有一个仅限 lambda 的解决方案,您将必须执行某种形式的递归函数。在我的脑海中,以下内容可以工作,但我不确定它将如何应对性能方面的问题:
You could significantly narrow your search down with a lambda expression something like:
Update
Actually the first solution won't traverse through properly. I don't think there is a lambda-only solution to this, you will have to do some form of recursive function. Off the top of my head the following would work, how it would cope performance wise I am unsure: