永远迷失在 if、while 和 foreach 语句中 - 无法获得适当的条件来运行

Posted

技术标签:

【中文标题】永远迷失在 if、while 和 foreach 语句中 - 无法获得适当的条件来运行【英文标题】:Forever lost in if, while and foreach statement - cannot get the appropriate condition to run 【发布时间】:2016-03-30 00:11:38 【问题描述】:

我在这个问题上花了相当多的时间,它很基本,但很快就失控了。

因为它相当令人困惑,所以我将发布我想要它做什么以及它实际做什么

目标

如果一个主管忙,它将转到下一个,如果他们都忙,它将显示一条消息“对不起,所有主管都忙”。对所有员工也是如此。

方法

我希望该方法读取所有主管,如果一个不忙则继续向下,然后我希望它读取所有员工,如果一个不忙则继续向下。

然后它会读取员工是否具有适当的技能以及是否已经取得成功,以避免同一个人被分配相同的工作。

如果到目前为止一切正常,它会检查主管是否被占用,如果是,它会恢复并更改主管。

然后它为员工分配信息,同时为主管分配一些信息并检查“成功”条件。

从这里开始有点草率了,正如你所看到的,我已经放置了许多布尔语句来简单地让程序退出循环并退出它。

在所有这一切之后,程序分配了工作,到目前为止,它在合理的程度上工作,但我希望有一条消息指出,如果所有主管都忙,则无法分配更多工作。

我过去曾在 foreach 语句后使用 MessageBox.Show,但如果一位主管很忙,它会显示我不想要的消息。

代码

分配作业的方法

bool finishLast = false;
bool successFirst = false;
while (successFirst != true)

    foreach (Supervisor sup in supervisors)
    
        bool failure = false;
        while (failure != true)
        
            foreach (Employee emp in employees)
            
                if (emp.Busy == false && emp.Skills.HasFlag(_skillRequired) && successFirst == false)
                
                    if (sup.SupervisorOccupied == false)
                    
                        successFirst = true;
                        emp.EmployeeWorkload = _jobName;
                        emp.ShiftsLeft = _shiftsLeft;
                        emp.Busy = true;
                        sup.EmployeeWorkload = "Supervising Employee: " + emp.EmployeeName + " to finish task: " + emp.EmployeeWorkload;
                        sup.ShiftsLeft = _shiftsLeft;
                        sup.SupervisorOccupied = true;
                    
                
                else if (emp.Busy == true)
                
                    failure = true;
                
            
        
        if (failure == true)
        
            finishLast = true;
        
    
    if (finishLast == true)
    
        successFirst = true;
    

当然,如果有人能想到一个更简单的方法,我会接受想法。

编辑 1

这不是一个多线程系统,是的,emp.Busysup.SupervisorOccupied 在技术上是一样的,它们都在 same class 中,所以是的,sup 可以继承 emp.Busy

【问题讨论】:

您能否更新您的问题并添加一个真正的“目标”?你首先描述你在做什么,而不是结果应该是什么。我猜您正在为用户分配工作,但我不完全清楚应该如何发生以及您的出发点是什么。 重新阅读您的代码后,您似乎想要执行以下操作: 找到一个可用的主管。找到具有该工作技能的可用员工。将工作分配给员工,并指派主管监督该员工的工作。如果这是正确的,那么您根本就不应该有嵌套循环。 我建议你删除所有 while 循环而不是必需的布尔值,因为它们非常令人困惑 我也很难理解这段代码的含义,这本身就是一个问题,就像它明显缺乏正确性一样。有几件事会有所帮助。首先,停止if (x != true) 等。等式产生一个布尔值,但布尔值已经布尔值!如果您的意思是if (x == true)while (x == true),只需说if (x)while (x)。而不是if (x == false) -- 如果 x 是真的,那么 x 是假的 -- 比如说 if (!x) -- 如果 x 的反面是真的。 第二,把这个东西分解成更小的方法,每个方法在问题的条件下做一些事情。就像 Lasse 所说,如果问题的一部分是要找到一个可用的主管,那么应该有一个方法 FindAvailableSupervisor 如果没有这样的主管,则返回一个主管或 null。编写那个方法,测试一下,现在你有了一个子系统,你可以依靠它来解决更大的问题。尝试根据业务领域编写问题陈述,而不是您打算如何编写代码。 【参考方案1】:

我认为这样的事情应该可行:

        bool assigned = false;
        foreach (Supervisor sup in supervisors)
        
            if (!sup.SupervisorOccupied)
            
                foreach (Employee emp in employees)
                
                    if (!emp.Busy && emp.Skills.HasFlag(_skillRequired))
                    
                        assigned = true;
                        emp.EmployeeWorkload = _jobName;
                        emp.ShiftsLeft = _shiftsLeft;
                        emp.Busy = true;
                        sup.EmployeeWorkload = "Supervising Employee: " + emp.EmployeeName + " to finish task: " + emp.EmployeeWorkload;
                        sup.ShiftsLeft = _shiftsLeft;
                        sup.SupervisorOccupied = true;
                        break;
                    
                
            
            if (assigned)
                break;
        

如果最后“assigned == false”,则没有可用的员工(实际上缺少一些代码,因此无法运行,但理论上它应该做你想做的事!)。

【讨论】:

太好了,这似乎奏效了,我知道我已经把它复杂化了,但是在凌晨 4 点,一个人无法重新制定想法,我会在短时间内奖励你的答案跨度> 好丹尼很乐意提供帮助。还要看看其他答案,因为您必须有机会选择实施,请“接受”答案,谢谢【参考方案2】:

下面是你应该如何编写代码:

var availableSupervisor = supervisors
    .FirstOrDefault(supervisor => !supervisor.SupervisorOccupied);
if (availableSupervisor == null)
    return;

var availableEmployee = employees
    .FirstOrDefault(employee => !employee.Busy && employee.Skills.HasFlag(_skillRequired));
if (availableEmployee == null)
    return;

availableEmployee.EmployeeWorkload = _jobName;
availableEmployee.ShiftsLeft = _shiftsLeft;
availableEmployee.Busy = true;
availableSupervisor.EmployeeWorkload = "Supervising Employee: " + emp.EmployeeName + " to finish task: " + emp.EmployeeWorkload;
availableSupervisor.ShiftsLeft = _shiftsLeft;
availableSupervisor.SupervisorOccupied = true;

【讨论】:

其实我不太喜欢用Exceptions来控制程序流程。即使他说这不是一个多线程环境,我认为很容易发生这样的一段代码,执行循环(可能在那里花费一段时间)稍后移动到一个计时器中:在这种情况下管理异常会肯定比更新一个外部“状态”对象更复杂,该对象还可以携带有关操作进度的信息(以及最终结果 - “分配的”布尔值 - 显然) 虽然从长远来看,您的答案看起来是最有效的,但我选择了一个适合我工作环境的答案,同时我很感谢您的 cmets 和答案,请不要认为我有忽略了你的努力。谢谢。 @Lasse:如果将.Where(supervisor => !supervisor.SupervisorOccupied).FirstOrDefault() 替换为.FirstOrDefault(supervisor => !supervisor.SupervisorOccupied),这段代码会更简洁一些。显然你可以对availableEmployee做同样的事情。 @LeonardoSpina:我同意你的观点,我不喜欢使用异常,但我确实认为 Lasse 的方法远远优于 OP 的现有方法。异常可以用循环代替。 Danny,我强烈建议你采用 Lasse 的方法;您对嵌套循环的使用更难遵循。嵌套循环方法的效率也较低,但这很容易在员工循环下使用额外的 break 语句来解决(即,如果您找不到第一个主管的空闲员工,也不要费心检查下一个主管)。 异常只是处理这些情况的一种方法,返回语句等等,还有很多其他方法来处理这些退出点。

以上是关于永远迷失在 if、while 和 foreach 语句中 - 无法获得适当的条件来运行的主要内容,如果未能解决你的问题,请参考以下文章

在 foreach 循环中的 if 语句中的 while 循环...无法正常工作

PHP - If/else, for, foreach, while - 没有花括号?

生产者消费者模式中条件判断是使用while而不是if

for/inforwhiledo/while 循环和 forEach 遍历的跳过和中断

JSTL 中c:forEach 嵌套c:if

流程控制