Поиск пробелов между 2D-массивом данных сотрудника и 2D-массивом данных отдела

#python #arrays

#python #массивы

Вопрос:

Эй, ребята, я работаю с набором данных, который содержит 14 столбцов (идентификатор отдела, идентификатор сотрудника и месяцы года), показывающих, сколько часов каждый сотрудник работал за каждый месяц.

Функция, с которой я работаю, должна распечатать строку для сотрудников, которые записывают нулевое значение за определенный месяц, когда его / ее отдел (в целом) записал ненулевое значение (т. Е. Джон в маркетинге записал нулевые часы за май, когда общее количество отделов составило 500 часов, поэтому мы печатаем Джонастрока).

У меня есть две вспомогательные функции: cost_center_sum(A) которая принимает 2D-массив данных (организованный в виде списка списков) и находит совокупные часы для каждого отдела в виде списка списков. Вторая вспомогательная функция, compcols(row, A) , сопоставляет идентификатор отдела «row» с соответствующей строкой в наборе данных A и проверяет, соответствует ли нулевое значение в «строке» для определенного месяца нулю за тот же месяц в строке, соответствующей в A.

Я попытался скомпилировать эти две функции в функцию, findgaps(A) , которая печатает информацию о сотруднике для сотрудника, который записывает ноль в течение месяца, когда отдел записал ненулевое значение.

Ниже приведен код для функций, которые я описал выше:

 def compcols(row, A):
for i in range(len(A)):
    if len(A[i]) < len(row):
        print row, (" - beware : line %d len(A[i]) %d < len(row) %d"
                    %(i, len(A[i]), len(row)))
    else:
        if row[0]==A[i][0]:
            for j in range(len(row)):
                if row[j]==0 and A[i][j]!=0:
                    print row
                    break


NUMBER_OF_MONTHS = 12
def cost_center_sum(A):
    dep = dict()
    for row in A:
        if row[0] not in dep:
            dep[row[0]] = [0.0 for x in xrange(NUMBER_OF_MONTHS)]
        for i in xrange(NUMBER_OF_MONTHS):
            dep[row[0]][i]  = row[i 2]
    ret = list()
    for department in sorted(dep.iterkeys()):
        x = [department]
        x.extend(dep[department])
        ret.append(x)
    return ret

def findgaps(A):
    X=cost_center_sum(A)
    for i in range(len(A)):
        for j in range(len(A[0])):
            if A[i][j] < 0.00001:
                return compcols(A[i],X) 
  

Я протестировал другие функции, и они, похоже, выполняют свою работу довольно хорошо (есть небольшая ошибка, при compcol которой одна и та же строка выводится несколько раз), но когда я использую findgaps функцию, она выдает совершенно неверный вывод только одной строки сотрудника, напечатанной 80 раз:

 [10017.0, 93454.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.6, 0.0]  - beware : line 76 len(A[i]) 13 < len(row) 14
[10017.0, 93454.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.6, 0.0]  - beware : line 77 len(A[i]) 13 < len(row) 14
[10017.0, 93454.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.6, 0.0]  - beware : line 78 len(A[i]) 13 < len(row) 14
[10017.0, 93454.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.6, 0.0]  - beware : line 79 len(A[i]) 13 < len(row) 14
[10017.0, 93454.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.6, 0.0]  - beware : line 80 len(A[i]) 13 < len(row) 14
  

Ответ №1:

findgaps выполняется только return один раз; после первого вызова compcols функция завершается:

 def findgaps(A):
    X=cost_center_sum(A)
    for i in range(len(A)):
        for j in range(len(A[0])):
            if A[i][j] < 0.00001:
                return compcols(A[i],X) # only ever returns once
  

Вместо этого это должно быть что-то вроде:

 def findgaps(A):
    X = cost_center_sum(A)
    for row in A:
        if any(month < 0.00001 for month in row[2:]):
            yield compcols(row, X)
  

Это «генератор», который будет возвращать несколько значений. Обратите внимание, что вам не нужны индексы i и j — они только усложняют код, и вы можете увидеть, насколько он понятнее, когда вы перебираете сами объекты.

Далее compcols сообщается о «предупреждениях» независимо от того, соответствует ли первый элемент или нет. Я думаю, что вместо этого должно быть:

 def compcols(row, X):
    for dept_row in X:
        if row[0] == dept_row[0]:
            for emp_month, dep_month in zip(row[2:], dept_row[2:])
                if emp_month == 0 and dep_month != 0:
                    return row
    else:
        print "No match for department {0}.".format(row[0])