【问题标题】:Is there a quick way to loop through lists that need to be sorted after each iteration of a for loop?有没有一种快速的方法来循环遍历每次 for 循环迭代后需要排序的列表?
【发布时间】:2020-08-18 10:22:54
【问题描述】:

目标 我目前正在用 Python 创建一个模拟,以测试代理的各种负载平衡,以获取服务级别内的传入工作。我将简化场景,希望有人能引导我朝着正确的方向前进。

我们的调用分为优先级:Alpha、Beta、Gamma。 Alpha 是最高优先级,Gamma 是最低优先级。为了确保我们不会错过服务级别,有时我们会“锁定”我们的员工,以便他们只能处理 Alpha 卷。

我做了什么 构建所有类:Day、Interval、Call、Agent。 我已经成功创建了一个由 48 个半小时间隔组成的一天。每个间隔都有自己的人员、平均处理时间和预测量属性。我添加了多种方法来跟踪呼叫是否已被拥有或完成以及代理何时可用。

模拟一天 呼叫位于按出现时间(升序)排序的列表中。我正在遍历此列表,并查找在提供呼叫之前或当时有多少呼叫未处理。在时间 (t),缓冲区中可能存在任意数量的调用。此列表按最高优先级的最早调用排序。所以在 calls[0] 是首先需要获取的调用:

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 <= call.Presented_Time and call.Completed is False and call.Owned is False]:

获得可用呼叫列表后,我会遍历我的代理并为最旧的最高优先级呼叫找到合适的匹配项。代理列表按 Busy_Until 排序。在 agent[0] 处,是 Busy_Until 值最低且最先接到另一个呼叫的座席。

for agent in [agt for agt in sorted(curr_day.Staff, key=lambda x: x.Busy_Until, reverse=False)]:

为了检查调用是否与代理匹配,我​​首先要验证一些 if 语句。

if active_call.Priority in agent.Lb:
    if agent.Busy_Until <= active_call.Presented_Time:
        agent.assign_call(active_call, active_call.Presented_Time)
        break
    else:
        agent.assign_call(active_call, agent.Busy_Until)
        break

注意事项 将警报分配给座席的行为会将座席的 Busy_Until 属性更改为他们接到呼叫的时间 + 呼叫的平均处理时间。然后将呼叫标记为已拥有,因此其他代理无法再次看到它。 Agent.Lb 是代理开放的所有优先级的列表。如果代理的 Busy_Until 属性小于或等于呼叫的呈现时间,则将其提供给他们。如果代理的 Busy_Until 属性大于呼叫的呈现时间,则在他们完成后将其提供给他们。

问题 此方法需要很长时间才能完成。事实上,我等了 10 分钟后并没有看到程序完成执行。我们每天看到大约 6,000 个呼叫,因此循环遍历所有呼叫非常耗时。我没有看到任何其他方法可以做到这一点。不过,我知道必须有一种优雅、高效的方式来做到这一点。

完整代码(减去类)

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 <= 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 <= active_call.Presented_Time:
                    agent.assign_alarm(active_alarm, active_alarm.Presented_Time)
                    break
                else:
                    agent.assign_call(active_call, agent.Busy_Until)
                    break

感谢任何可以提供一点指导的人。

【问题讨论】:

  • 您选择的数据结构似乎不合适 - 即使只有个别项目发生变化,您仍在对所有内容进行排序。您是否考虑过使用固有索引结构(例如dict)或固有排序结构(例如heapq)?还有各种第三方库,例如sortedcontainers,提供更合适的数据结构。
  • 在每次外部迭代中,您都会一遍又一遍地对列表进行排序和过滤。尝试将尽可能多的常用功能移出循环(例如,排序和过滤属性不依赖于call
  • @MisterMiyagi,感谢您提供的信息!我将使用 heapq,因为它似乎是我正在寻找的。​​span>
  • @SebastianHoffmann,不幸的是,由于调用流程的性质,我必须在每次迭代后对其进行排序。我基本上是在呈现新呼叫时模拟优先级未处理呼叫的缓冲区。
  • 请注意,PriorityQueue 也可能适用于此。它基本上是heapq 的包装器。

标签: python list loops nested


【解决方案1】:

我能够找到满足问题的解决方案。因为每个警报都是存储桶的一部分,并且每个代理都分配给一个存储桶,所以我刚刚创建了一个列表字典。在 dict['Alpha'][0] 是最重要的 alpha 调用,dict['Beta'][0] 是最重要的 beta 调用,等等。

我为缓冲区创建了一个类。初始化时,为每个桶中的每个优先级创建一个空白字典。新调用通过附加方法添加到此缓冲区的相应索引中。这是课程:

class Buffer:
def __init__(self):
    self.Alarms = self.__create()

def __create(self):
    queue = defaultdict(list)
    for pri in range(30):
        queue[pri] = []
    return queue

def add(self, alarm_obj):
    self.Alarms[alarm_obj.Priority].append(alarm_obj)

def get_next_for_agent(self, agent_obj):
    for pri in agent_obj.Lb:
        if len(self.Alarms[pri]) != 0:
            return self.Alarms[pri].pop(0)

这里是主要代码:

curr_day = Day()
alarm_buffer = Buffer()

for interval in curr_day.Intervals:
    for alarm in interval.Alarms:
        alarm_buffer.add(alarm)
        active = interval.get_active_staff(alarm.Presented_Time)
        for agent in active:
            a = alarm_buffer.get_next_for_agent(agent)
            if a is not None:
                if a.Presented_Time <= agent.Busy_Until:
                    obtained = agent.Busy_Until
                else:
                    obtained = a.Presented_Time
                agent.assign_alarm(a, obtained)
                break

curr_day.export_results()

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多