title: Is there a quick way to loop through lists that need to be sorted after each iteration of a for loop?
body: <p><strong>Objective</strong>
  I am currently in the process of creating a simulation in Python to test various load balances for agents to obtain incoming work within service level. I will simplify the scenario in hopes that someone can steer me in the right direction.</p>
  
  <p>Our calls are broken up into priorities: Alpha, Beta, Gamma. Alpha being the highest priority and Gamma being the least priority. To ensure we don't miss service levels, sometimes we will "lock down" our staff so they can only handle Alpha volume.</p>
  
  <p><strong>What I've done</strong>
  All classes are built: Day, Interval, Call, Agent.
  I've successfully created a day composed of 48, half hour intervals. Each interval has its own staff, average handle time, and forecast volume attributes. There are various methods that I've added to track if the call is owned or completed and when the agent becomes available next.</p>
  
  <p><strong>Simulating the day</strong>
  The calls are in a list sorted by the time they are presented (ascending). I am looping through this list and finding how many calls are unhandled before or at the time the call is offered. At time (t), there may exist any number of calls in the buffer. This list is sorted by oldest call of highest priority. So at calls[0] is the call that has needs to be obtained first and foremost:</p>
  
  <pre><code>for call in curr_day.Calls:
      for active_call in [c for c in sorted(curr_day.Calls, key=lambda x: x.Priority, reverse=False) if c.Presented_Time &lt;= call.Presented_Time and call.Completed is False and call.Owned is False]:
  </code></pre>
  
  <p>Once I get the list of available calls, I then loop through my agents and find a suitable match for the oldest call of highest priority. The agent list is sorted by Busy_Until. At agents[0] is the agent who has the lowest value for Busy_Until and is first to get another call.</p>
  
  <p><code>for agent in [agt for agt in sorted(curr_day.Staff, key=lambda x: x.Busy_Until, reverse=False)]:</code></p>
  
  <p>To check if the call is a match for the agent, I have some if statements to validate first.</p>
  
  <pre><code>if active_call.Priority in agent.Lb:
      if agent.Busy_Until &lt;= active_call.Presented_Time:
          agent.assign_call(active_call, active_call.Presented_Time)
          break
      else:
          agent.assign_call(active_call, agent.Busy_Until)
          break
  </code></pre>
  
  <p><strong>Notes</strong>
  The act of assigning an alarm to an agent changes the agent's Busy_Until attribute to the time they got the call + average handle time of the call. The call is then tagged as owned, so it can't be seen again by other agents. Agent.Lb is a list of all priorities an agent is open to. If the agent's Busy_Until attribute is less than or equal to the call's presented time, give it to them. If the agent's Busy_Until attribute is greater than the call's presented time, give it to them when they're done.</p>
  
  <p><strong>Issues</strong>
  This method takes WAY too long to complete. In fact, I didn't see the program complete execution after waiting 10 minutes. We see about 6,000 calls a day, so looping through all of them is very time intensive. I don't see any other way to do this; though, I know there has to be an elegant, efficient way to do so.</p>
  
  <p><strong>Complete code (minus classes)</strong></p>
  
  <pre><code>curr_day = Day()
  
  for call in curr_day.Calls:
      for active_call in [c for c in sorted(curr_day.Calls, key=lambda x: x.Priority, reverse=False) if c.Presented_Time &lt;= call.Presented_Time and c.Completed is False and c.Owned is False]:
          for agent in [agt for agt in sorted(curr_day.Staff, key=lambda x: x.Busy_Until, reverse=False)]:
              if active_call.Priority in agent.Lb:
                  if agent.Busy_Until &lt;= active_call.Presented_Time:
                      agent.assign_alarm(active_alarm, active_alarm.Presented_Time)
                      break
                  else:
                      agent.assign_call(active_call, agent.Busy_Until)
                      break
  </code></pre>
  
  <p>To anyone that can provide even a little bit of guidance, I thank you.</p>