以列表作为值在两个字典上进行迭代

时间:2019-10-02 14:03:32

标签: python dictionary key-value

我有关于员工打卡时间的数据。

员工可以通过自动流程(通过他的钥匙卡或指纹)或通过简单的Web表格手动报告开始时间。

问题在于,有些员工不小心报告了不止一种方法的时间

输入流数据分为两个字典,其值如下所示:

如果员工在特定日期登录,我将尝试对两个字典进行迭代并计数(而不是总和)。

def count_type(logins, punch_clock_data):
    counter = 0
    ans_dict = {}
    for punch_clock_key, punch_clock_value in punch_clock_data.items():
        for element in punch_clock_value:
            if element not in ans_dict:
                l1 = logins.get(element)
                for i in range(len(l1)):
                    if i == 1:
                        counter+=1
                        break
            ans_dict[punch_clock_key] = counter
        print(f'this employee was at work {counter} days this week by {punch_clock_key} login')
    return ans_dict


# each item in the array is a representation of weekday. for example, 
# on Sunday there was not any log in data.
# on Tuesday, this employee reported login both on web form and by 
# card(flag = 1) etc.


logins = { 'card'        :[0, 1, 1, 0, 0, 0, 0],
           'fingerprint' :[0, 0, 0, 1, 1, 0, 0],
           'web form'    :[0, 0, 1, 1, 0, 1, 1]
}


# dictionary contains data on types of punch clock
punch_clock_data  = { 'automated' :['card', 'fingerprint'],
                      'manual'    :['web form'],
                      'all_types' :['card', 'fingerprint', 'web form']
}

res = count_type(logins, punch_clock_data)
print(res)

我的输出与预期不符。 这是我的输出

{'automated': 2, 'manual': 3, 'all_types': 6}

但是我想要得到的是:

{'automated': 4, 'manual': 4, 'all_types': 6}
  • “自动”应为4,因为这是4天标志等于1(星期一,星期二使用卡,星期三,星期四使用指纹
  • 手册应为4,因为这是四天标志等于1的天(周二,周三,周五,周六)
  • all_types应该为6,因为这是六天,其中至少一个标志等于1。

我认为我的问题是我需要按索引而不是按值对所有工作日列表进行迭代。 对于一周中的每一天,获取正确的索引并对其进行计数(垂直而非水平)

3 个答案:

答案 0 :(得分:3)

看起来您只希望在特定打孔时钟类别中员工通过多种方法登录的那一天进行一次登录。您可以将每个类别的登录方法列表压缩在一起,并测试其中是否有一个登录名。

logins = {'card': [0, 1, 1, 0, 0, 0, 0], 'fingerprint' :[0, 0, 0, 1, 1, 0, 0], 'web form': [0, 0, 1, 1, 0, 1, 1]}
punch_clock_data = { 'automated': ['card', 'fingerprint'], 'manual': ['web form'], 'all_types': ['card', 'fingerprint', 'web form']}

results = {}
for group, keys in punch_clock_data.items():
    results[group] = sum(any(t) for t in zip(*[logins[k] for k in keys]))

print(results) 
# {'automated': 4, 'manual': 4, 'all_types': 6}

根据您的评论请求一个版本,该版本使查看相关步骤变得更加容易。这里有一些故障。

results = {}
for group, keys in punch_clock_data.items():
    # list of lists of logins for each method in the category
    all_logins = [logins[k] for k in keys]

    # zip all_logins by day of the week
    logins_per_day = zip(*all_logins)

    # add 1 for each day where any of the values in the tuple are not zero
    results[group] = sum(any(t) for t in logins_per_day)

答案 1 :(得分:1)

看这段代码

def count_type(logins, punch_clock_data):
    ans_dict = {}
    for punch_clock_key, punch_clock_value in punch_clock_data.items():
        counter = 0
        tmp_tab = [0] * 7
        for login_key in punch_clock_value:
            for i in range(len(logins[login_key])):
                tmp_tab[i] += logins[login_key][i]
        for day in tmp_tab:
            counter += day > 0
        ans_dict[punch_clock_key] = counter
    return ans_dict

对于具有all_types的示例,我创建了一个tmp_tab来转换您的3个标签页

[0, 1, 2, 2, 1, 1, 1]

然后,如果col的值大于等于0,则为每个col和计数器的和+ = 1

答案 2 :(得分:1)

此处的密钥,您需要像这样的SUM登录,例如all type

       'card':        [0, 1, 1, 0, 0, 0, 0]
       'fingerprint' :[0, 0, 0, 1, 1, 0, 0]
       'web form'    :[0, 0, 1, 1, 0, 1, 1]
       'all type'    :[0, 1, 1, 1, 1, 1, 1]  total = 6

所以您可以尝试:

NUMBER_OF_DAY = 7
def count_type(logins, punch_clock_data):
    ans_dict = {}
    for punch_clock_key, punch_clock_values in punch_clock_data.items():
        # list of all login
        element_list = [logins[punch_clock_value] for punch_clock_value in punch_clock_values]
        # compute the sum of each day
        # EX:
        # [0, 1, 1, 0, 0, 0, 0] + [0, 0, 0, 1, 1, 0, 0]
        # total equal to = [0, 1, 1, 1, 1, 0, 0]
        total_days = [0] * NUMBER_OF_DAY
        for element in element_list:
            for day_index, is_checked in enumerate(element):
                # if he checked is_checked == 1 else is 0 
                if is_checked:
                    # he checked in day mark this in the total by 1 not by some
                    total_days[day_index] = 1

        # now just some the total of day
        ans_dict[punch_clock_key] = sum(total_days)
    return ans_dict

综合使用zip,zip和list有助于减少代码:

def count_type(logins, punch_clock_data):
    ans_dict = {}
    for punch_clock_key, punch_clock_values in punch_clock_data.items():
        # list of all login
        element_list = [logins[punch_clock_value] for punch_clock_value in punch_clock_values]
        # zip them so when we iterate over them we get a tuple of login of one day in each iteration
        element_list = zip(*element_list)
        total = 0
        for days in element_list:   
           total += any(days) and 1 or 0
        ans_dict[punch_clock_key] = total
    return ans_dict

现在,我们可以进一步简化代码:

  element_list = [logins[punch_clock_value] for punch_clock_value in punch_clock_values]
  element_list = zip(*element_list)

  # to this 
  element_list = zip(*[logins[punch_clock_value] for punch_clock_value in punch_clock_values])

感谢build-in sum

    total = 0
    for days in element_list:   
       total += any(days) and 1 or 0
    ans_dict[punch_clock_key] = total


    # to this 
    ans_dict[punch_clock_key] = sum(any(days) for days in element_list)

最后的结果函数:

def count_type(logins, punch_clock_data):
    ans_dict = {}
    for punch_clock_key, punch_clock_values in punch_clock_data.items():
        # list of all login
        element_list = element_list = zip(*[logins[punch_clock_value] for punch_clock_value in punch_clock_values])
        ans_dict[punch_clock_key] = sum(any(days) for days in element_list)
    return ans_dict