【问题标题】:ForEach Loop to start from Middle/Anywhere of List/Collection and then traverse to all itemsForEach 循环从 List/Collection 的 Middle/Anywhere 开始,然后遍历所有项
【发布时间】:2018-08-15 09:03:54
【问题描述】:

我需要从多级树视图中的当前选定项目中搜索列表中的内容。我的树视图中有 4 个级别,并在第 4 级搜索符合某些条件的节点。请看下图:

现在在这张图片中,我正在搜索里面有 1 个的红色块(失败的一个)。以下是我要搜索的代码:

foreach (var Project in Projects)
{
    foreach (var Devices in Project.TestRuns)
    {
        foreach (var Category in Devices.TestModuleCategories)
        {
            foreach (var TestModule in Category.TestModules)
            {
                foreach (var statement in TestModule.TestModuleStatementList)
                {
                    if (statement.TestsFailed == 1 && !statement.IsSearched)
                    {
                        TestModule.TestModuleStatementList.ForEach(f => { f.IsCurrentFocused = false; });
                        statement.IsCurrentFocused = true;
                        statement.IsSearched = true;
                        TreeViewItem item = GetTreeViewItem(ViewTestDataTree, statement);
                        item.IsExpanded = true;
                        //ViewTestData.SetSelectedItem(ref ViewTestDataTree, item);
                        //item.Focus();
                        return;
                    }
                    statement.IsCurrentFocused = false;
                }

            }
        }
    }
}

Projects.ForEach(a => a.TestRuns.ForEach(b => b.TestModuleCategories.ForEach(c => c.TestModules.ForEach(d => d.TestModuleStatementList.ForEach(f => { f.IsSearched = false; })))));

现在的问题是我每次搜索时都在运行 foreach 循环,但我希望如果用户在任何地方的列表中间,那么搜索应该从那里开始到列表的最后一个,并且从顶部开始剩余的列表。是否有任何机制可以从集合的任何位置开始并从下到上搜索所有节点?

【问题讨论】:

  • 你为什么不尝试正常的 for(int i=startFirst; i
  • 如果您已经在Projects 上执行foreach,那么您为什么还要在所有事情上调用ForEach?这是重写还是什么?
  • 我正在使用 foreach,因为 Projects 有一个 TestRuns 集合,而 TestRuns 有一个集合,直到 TestModuleStatementList,我想在 TestModuleStatementList 上进行搜索。现在我想从用户当前关注树视图的位置开始搜索,所以无论如何要启动 foreach 循环以从特定集合开始,然后遍历完整列表?
  • 我认为这是我见过的嵌套最多的foreach循环
  • @PankajBhatia 又来了!这就是为什么有标准的循环。 for(int i=startIndex; istackoverflow.com/questions/1211608/…

标签: c# wpf


【解决方案1】:

我建议将您的 foreach 循环封装在一个返回搜索结果的 IEnumerable 实例的方法中:

IEnumerable<Statement> Search(/* put parameters here*/)
{
     Foreach(...)
         Foreach(...)
            Foreach(...)
              Foreach(...)
              {
                  if(...)
                     yield return statement;
              }
}

并且在你的主搜索管理中,保留一个 IEnumerator 对象的实例,以便直接切换到下一个搜索结果:

 IEnumerator<Statement> searchResults;
 void NextResult()
 {
     if (searchResults == null)
         searchResults = Search( /* parameters...*/).GetEnumerator();

      if (!searchResults.MoveNext())
     {
         // In this situation we have reached the end of the tree
         // Restart from the beginning
         searchResults.Reset();
         searchResults.MoveNext();
     }

     var statement = searchResults.Current;
     if (statement != null)
     {
         // ...
         // Actions regarding current statement
         // ...
     }
 }

当然,解决方案应该适应搜索条件的变化。

【讨论】:

    【解决方案2】:

    您可以创建另一个列表来展平您的树:

    List<TestModuleStatement> statements = new List<TestModuleStatement>(); // guessing at class name
    
    Projects
        .ForEach(a => a.TestRuns
        .ForEach(b => b.TestModuleCategories
        .ForEach(c => c.TestModules
        .ForEach(d => d.TestModuleStatementList
        .ForEach(f => { statements.Add(f); })))));
    

    然后你可以使用一个 while 循环,从当前位置 + 1 开始并环绕从当前位置开始并在当前位置之前结束:

    int selectedIndex = statements.FindIndex(f => f.IsCurrentFocussed);
    int searchPos = (selectedIndex + 1) % statements.Count;
    while (searchPos != selectedIndex)
    {
        if (statement.TestsFailed == 1 && !statement.IsSearched)
        {
            statements.ForEach(f => { f.IsCurrentFocused = false; });
            statement.IsCurrentFocused = true;
            statement.IsSearched = true;
            TreeViewItem item = GetTreeViewItem(ViewTestDataTree, statement);
            item.IsExpanded = true;
            return;
        }
        searchPos = (selectedIndex + 1) % statements.Count;
    }
    

    【讨论】:

    • @Pankaj 如果解决了您的问题,请确认此为答案
    【解决方案3】:

    For each 循环不提供按索引访问(它只保存指向当前项和集合中下一项的指针),因此每次都会从头开始。

    【讨论】:

      猜你喜欢
      • 2017-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-02
      相关资源
      最近更新 更多