在Python 3.6中迭代添加元素时重复元素的问题

3

我正在尝试编写一段代码,从两个不同的列表中获取元素并进行匹配,如下所示,但出现了重复元素,导致输出列表中也有重复元素。

def assign_tasks(operators, requests, current_time):
    """Assign operators to pending requests.

    Requires:
    - operators, a collection of operators, structured as the output of 
      filesReading.read_operators_file;
    - requests, a list of requests, structured as the output of filesReading.read_requests_file;
    - current_time, str with the HH:MM representation of the time for this update step.
    Ensures: a list of assignments of operators to requests, according to the conditions indicated 
    in the general specification (omitted here for the sake of readability).
    """
    operators = sorted(operators, key=itemgetter(3, 4, 0), reverse=False)
    requests = sorted(requests, key=itemgetter(3), reverse=True)
    isAssigned = 0
    tasks = []
    langr = 0 #Variable that gets the language of the request's file (customer's language)
    lango = 0 #Variable that gets the language of the operator's file (operator's language)
    for i in range(len(requests)-1):
        langr = requests[i][1]                                   #What language does the customer speaks?
        for k in range(len(operators)-1):
            lango = operators[k][1]                              #What language does the operator speaks?
            if langr == lango:                                   #Do they speak the same language?
                for j in range(len(operators[k][2])-1):
                    if (operators[k][2][j] == requests[i][2]) and (operators[k][4] <= 240):     # The operator knows how to solve the client's problem? If yes, then group them together.
                        a = operators[k][2][j]
                        b = requests[i][2]
                        tasks.append([current_time, requests[i][0], operators[k][0]])
                        operator_time = operators[k][4]
                        request_time = requests[i][4]
                        new_operator_time = operator_time + request_time
                        operators[k][4] = new_operator_time
                        isAssigned == True
                        #operators.remove(operators[k])
                        requests.remove(requests[i])
                    else:
                        isAssigned = False
                    if isAssigned == False:
                        tasks.append([current_time, requests[i][0], "not-assigned"])

        operators = sorted(operators, key=itemgetter(3, 4, 0), reverse=False)

    return tasks, operators, requests

我的当前输入是这样的:

operators = [['Atilio Moreno', 'portuguese', ('laptops',), '10:58', 104], ['Leticia Ferreira', 'portuguese', ('laptops',), '11:03', 15], ['Ruth Falk', 'german', ('phones', 'hifi'), '11:06', 150], ['Marianne Thibault', 'french', ('phones',), '11:09', 230], ['Mariana Santana', 'portuguese', ('phones',), '11:11', 230], ['Beate Adenauer', 'german', ('hifi', 'phones'), '11:12', 140], ['Zdenka Sedlak', 'czech', ('phones',), '11:13', 56], ['Romana Cerveny', 'czech', ('phones',), '11:13', 213]]
requests = [['Christina Holtzer', 'german', 'hifi', 'fremium', 7], ['Andrej Hlavac', 'czech', 'phones', 'fremium', 9], ['Dulce Chaves', 'portuguese', 'laptops', 'fremium', 15], ['Otavio Santiago', 'portuguese', 'laptops', 'fremium', 15], ['Dina Silveira', 'portuguese', 'phones', 'fremium', 9], ['Rafael Kaluza', 'slovenian', 'laptops', 'fremium', 13], ['Sabina Rosario', 'portuguese', 'laptops', 'fremium', 10], ['Nuno Rodrigues', 'portuguese', 'laptops', 'fremium', 12], ['Feliciano Santos', 'portuguese', 'phones', 'fremium', 12]]

current_time = "14:55 06:11:2017"
print(assign_tasks(operators, requests, current_time))

我目前的输出是三个列表,例如,第一个列表就是这样的:

[[11:05, Christina Holtzer, not-assigned],[11:05, Christina Holtzer, Beate Adenauer],[11:05, Andrej Hlavac, not-assigned]]

你的代码没有正确缩进,请修正。 - Mad Physicist
实际输入是什么?如果不知道你输入了什么,很难弄清楚为什么会得到那个结果。 - Mad Physicist
@MadPhysicist 你好!我已经添加了输入信息。它到底哪里没有正确缩进? - Miguel Santana
嗨,@MiguelSantana,通常情况下这是一个反模式,除非您在使用索引时有其他目的而不仅仅是在列表中索引到该确切位置的元素。您是不是想要跳过列表中的最后一个元素? - juanpa.arrivillaga
1
虽然我再问一遍,你是不是有意在每个循环中跳过列表的最后一个元素?例如,执行 for i in range(len(x) - 1) 的效果将会在某个列表 x 中迭代所有除了最后一个索引之外的元素... 但我认为你得到了重复,是因为你正在循环遍历你两个列表的,而我认为你希望遍历每一对不同的元素。 - juanpa.arrivillaga
显示剩余16条评论
1个回答

3

我并不知道你需要什么样的逻辑,这并不是我的重点,我的重点是你可能无法专注于逻辑,因为你太忙于那些索引事情了。所以我自作主张地修改了你的代码,展示了什么是重要的,如果你使用python,你应该利用这个特性,因为可读性很重要。

from operator import attrgetter

class Person:
    def __init__(self, name, lan):
        self.name = name
        self.lan = lan

    def is_compatible(self, other):
        if other.lan == self.lan:
            return True
        return False

class Requester(Person):
    def __init__(self, *args, problem, mode, time, **kwargs):
        super().__init__(*args, **kwargs)
        self.problem = problem
        self.mode = mode
        self.time = time

class Operator(Person):
    def __init__(self, *args, expertise, hour, time, **kwargs):
        super().__init__(*args, **kwargs)
        self.expertise = expertise
        self.hour = hour
        self.time = time
        self.assigned = False

operators = [
    Operator(name='Atilio Moreno', lan='portuguese', expertise=('laptops',), hour='10:58', time=104),
          .
          .
          .
    Operator(name='Romana Cerveny', lan='czech',  expertise=('phones',), hour='11:13', time=213),
]

requests = [
    Requester(name='Christina Holtzer', lan='german', problem='hifi', mode='fremium', time=7),
          .
          .
          .
    Requester(name='Feliciano Santos', lan='portuguese',  problem='phones',  mode='fremium', time=12),
]

完成这一步后,思考逻辑的任务就变得更加简单了,只需将你所想的内容打出来即可。
def assign_tasks(operators, requests, current_time):
    operators.sort(key=attrgetter('hour', 'time', 'name'))
    requests.sort(key=attrgetter('mode'))
    tasks = []
    for requester in requests:
        for operator in operators:
            if requester.is_compatible(operator) and requester.problem in operator.expertise and operator.time < 240:
                if not operator.assigned:
                    tasks.append([current_time, requester.name, operator.name])
                    operator.assigned = True
                    operator.time += requester.time
                    break # Breaks out of second for-loop so we go to the next requester
        else: #In case no operator is available
            tasks.append([current_time, requester.name, 'not-assigned'])
    return tasks, operators, requests

tasks, operators, requests = assign_tasks(operators=operators, requests=requests, current_time=0)

print(tasks)

这的输出结果是:
 [[0, 'Christina Holtzer', 'Ruth Falk'], [0, 'Andrej Hlavac', 'Zdenka Sedlak'], [0, 'Dulce Chaves', 'Atilio Moreno'], [0, 'Otavio Santiago', 'not-assigned'], [0, 'Dina Silveira', 'not-assigned'], [0, 'Rafael Kaluza', 'not-assigned'], [0, 'Sabina Rosario', 'not-assigned'], [0, 'Nuno Rodrigues', 'not-assigned'], [0, 'Feliciano Santos', 'not-assigned']]

这有点长,但所有请求者都需要有操作员或没有操作员。

再次强调,我不知道这个逻辑是否符合您的要求,但我希望您能看到,采用这种方法可以更简单地思考问题(真正重要的是什么),并且对其他人阅读也更简单。


太好了!非常感谢你!但是我恐怕做不到,因为这是一个大学项目,而我还没有学习“类”机制。是的,那就是我要追求的逻辑!;) - Miguel Santana
@MiguelSantana你几乎可以只用namedtuple做同样的事情,唯一有困难的是“operator.time += requester.time”和“assigned = False”,因为元组是不可变的。 - Jose A. García
@JoseA。您可以使用类似于“'time'”和“'assigned'”这样的键的字典。这基本上就是一个简单类为您做的事情。 - Mad Physicist
@MadPhysicist 非常正确。这只是个人偏好,我不喜欢那些括号。而且这更加普遍。 - Jose A. García
@Jose 当然,我更喜欢你的解决方案。我只是针对OP对使用类的限制。 - Mad Physicist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接