Miguel Santana
Miguel Santana

Reputation: 247

Repeating elements when appending in iteration in Python 3.6

I am trying to code a portion of code that gets the elements from two distinct lists and make a match, as you can see below, but for some reason, I keep getting repeated elements on my output lists.

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

My current input is this:

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))

My current output is three lists where, for example, the first one is something like this:

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

Upvotes: 3

Views: 94

Answers (1)

Jose A. Garc&#237;a
Jose A. Garc&#237;a

Reputation: 888

I dont really know the logic you are after, that is not even my point, my point is that probably you can't focus on the logic because you are too busy with those index thing. So I have taken the liberty to modify your code a little bit to show what is important, and if you are using python, you should take advantage of this feature, because readability counts.

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),
]

With this done, the task of thinking about the logic becomes much simpler, just type what you are thinking:

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)

The output of this is:

 [[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']]

That's kinda long, but there are all the requester either they have an operator or not.

Again, I dont know if this logic is the logic you are after but I hope you see that with this approach it is simpler to think about the problem (what really matters) and it is also simpler for others to read.

Upvotes: 3

Related Questions