使用迭代器块减少嵌套的for循环和if语句

本文关键字:循环 for if 语句 嵌套 迭代器 | 更新日期: 2023-09-27 18:05:36

是否有可能减少这种长嵌套的for循环和if条件以增加其可读性并优化它以供将来参考?

在为我的日程安排应用程序编写代码时,我最终使用了如下所示的方法。实际上,我有一个这样的数据结构。在这里,I检查-是否有任何阶段(在LCycle内)同时使用相同的工具,如果发现是这样,则调用另一个方法LCycleTimeShift进行重新排列。

但是我想检查新的安排是否可适应,并重置for循环计数器,以便它再次检查新的安排。我认为这不是更好的方式来编写代码更好的可读性。我对这个话题做了一些研究,发现枚举员可以在这方面帮助我。但是我不知道如何用下面的代码来完成这个。

public List<LCycle> ToolArrangment(List<LCycle> TimeLineInit)
{
    for (int i = 0; i < TimeLineInit.Count; i++)//Each LIfeCycles In TimeLine
    {
        for (int j = 0; j < TimeLineInit[i].Stage.Count; j++)//Each Stages inTimeLine
        {
            for (int k = 0; k < i; k++)//Each L esvd =ifeCycles Upto Current LifeCycle
            {
                for (int l = 0; l < TimeLineInit[k].Stage.Count; l++)//Each Stages of (LifeCycle upto current LifeCycle) 
                {
                    for (int m = 0; m < TimeLineInit[i].Stage[j].ToolList.Count; m++)//each tools in stage of timelkine
                    {
                        for (int n = 0; n < TimeLineInit[k].Stage[l].ToolList.Count;n++ )// Each tools In that stage (for loop outer of outer)
                        {
                            if (TimeLineInit[i].Stage[j].ToolList[m].ToolName == TimeLineInit[k].Stage[l].ToolList[n].ToolName)//If both tools are same (satidfying above for loop conditions)
                            {
                                if (IsTimeOverLaps(TimeLineInit[i].Stage[j].StageSpan, TimeLineInit[k].Stage[l].StageSpan))
                                {//tool using at same time.
                                    Stage ReplaceStage = TimeLineInit[i].Stage[j].DeepCopy();//Taking Copy of stage Span to make time shift
                                    Double TimeDifference=(ReplaceStage.StageSpan.ToTime-ReplaceStage.StageSpan.FromTime).TotalMinutes;//Calculating required time shift
                                    ReplaceStage.StageSpan.FromTime=TimeLineInit[k].Stage[l].StageSpan.ToTime;//FromTime changed accordingly
                                    ReplaceStage.StageSpan.ToTime=ReplaceStage.StageSpan.ToTime.AddMinutes(TimeDifference);//To Time Changed accordingly
                                    LCycleTimeShift(TimeLineInit[i], ReplaceStage);//passing refernce
                                    j = 0; k = 0; l = 0; m = 0; n = 0;//Counter Reset to validate the new arrangment
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return TimeLineInit;
}

使用迭代器块减少嵌套的for循环和if语句

尝试使用LINQ,特别是SelectMany和Join方法

var t = TimeLineInit
          .SelectMany(t=>t.Stage)
          .SelectMany(s=>s.ToolList);
... 
t
 .Join(t, [your conditions 1])
 .Join(t, [your conditions 2])

在你走上这条路之前,有几件事要注意。代码现在工作了吗?你有单元测试吗?我之所以这么问,是因为在开始任何重构之前,如果你有测试用例,那就太好了。

关于枚举数,有一行代码引起了我的注意:
LCycleTimeShift(TimeLineInit[i], ReplaceStage);//passing refernce
j = 0; k = 0; l = 0; m = 0; n = 0;//Counter Reset to validate the new arrangment

不允许在枚举操作中修改集合,所以你可能会发现,无论你在函数中做了什么魔术,对于for(…)可以很好地工作,它可能不再适用于foreach(…)或LINQ枚举。只有当它正在向集合中删除、添加项时(它似乎正在这样做),才会出现这种情况。我必须在下面做一些更改,因为我假设枚举在每次传递后都会更改,这意味着我每次都要重新计算重复项。

正如你所说,似乎你想找到任何两个阶段(不属于同一个LCycle),包含在同一时间使用相同的工具。然后对该阶段的时间进行一些更改,然后修改父节点。对我来说很有意义。这是我想出来的。我没有任何测试用例,但它可能会让你在正确的方向。

var toolsInUse = TimeLineInit
                    .SelectMany(cycle => cycle.Stage
                    .SelectMany(stage => stage.ToolList.Select(tool => new
{
    Cycle = cycle,
    Stage = stage,
    Tool = tool.ToolName
})));
var duplicateUse = toolsInUse.Join(toolsInUse, 
                                    x => x.Tool, 
                                    x => x.Tool, 
                                    (a, b) => new { Use = a, Duplicate = b })
                                .Where(x => x.Use.Cycle != x.Duplicate.Cycle &&
                                            IsTimeOverLaps(x.Use.Stage.StageSpan, x.Duplicate.Stage.StageSpan));
while (duplicateUse.Count() > 0)
{
    var item = duplicateUse.First();
    Stage ReplaceStage = item.Use.Stage.DeepCopy();//Taking Copy of stage Span to make time shift
    Double TimeDifference = (ReplaceStage.StageSpan.ToTime - ReplaceStage.StageSpan.FromTime).TotalMinutes;//Calculating required time shift
    ReplaceStage.StageSpan.FromTime = item.Duplicate.Stage.StageSpan.ToTime;//FromTime changed accordingly
    ReplaceStage.StageSpan.ToTime = ReplaceStage.StageSpan.ToTime.AddMinutes(TimeDifference);//To Time Changed accordingly
    LCycleTimeShift(item.Use.Cycle, ReplaceStage);//passing refernce
}

我对性能、准确性没有任何要求。这只是给你们指出一个方向。

唯一合理的选择是将迭代内容作为相互调用的模型中的方法,这样它将更具可读性,并且更容易理解。