某大厂员工爆料:提了离职后公司电脑的灯一直亮着,细思极恐,都要走了,还要被时刻监控!
刚看到个贴子,说有大厂员工提了离职后,公司电脑指示灯一直亮着,明明关了摄像头还闪,搞得像被24小时监控一样,怪瘆人的。
很多公司确实装了各种安全管控软件,离职流程一跑,权限回收、数据备份、系统审计一堆动作,灯常亮也不一定真在监控你——但员工的恐惧感是真实的。
问题的根本还是在“透明度”。公司不提前说明、不解释清楚,让员工靠猜的,那自然容易引发误会。职场里最怕的不是制度严,而是莫名其妙的神秘操作。
不过话说回来,哪怕要管控,也得让人明白在管啥、为什么管。尊重感这东西,看不见,但扎心。【备注:文末可领最新资料】
面试题:查询员工的累计薪水
昨天晚上十一点多我还在公司楼下拿着奶茶刷工单,有个同事在群里问了句:“哥们儿,有没有现成的代码算员工累计薪水的?我这边报表要按月份累加那种。”我当时脑子一转,这不就是个前缀和问题嘛,用 Python 写两行就搞定的事,但一说就变成一长串,索性给你们完整唠一遍。
场景大概是这样的: 你有一堆发薪记录,每条记录里有三个关键字段:员工 ID、月份、当月发了多少钱。可能长这样:
emp_id month salary
1 202401 10000
1 202402 12000
1 202403 11000
2 202401 8000
2 202403 9000
领导要看的不是“每个月多少钱”,而是“看到这一个月为止,这个员工一共领了多少”。比如员工 1:
202401 累计 = 10000 202402 累计 = 10000 + 12000 = 22000 202403 累计 = 22000 + 11000 = 33000
员工 2 还会出现“中间没发工资记录”的情况(比如 202402 没记录),那就只对存在的月份做累计就好了,不用硬凑出所有月份。
用自然点的话说,就是: 按员工分组,再按月份排序,然后一路往前加,边加边记下来。
思路其实就两步
我当时在工位上随手在本子上画了个小图,思路就两句:
先按 emp_id 把记录分堆,每一堆再按 month 从小到大排个序。 遍历这一堆记录,维护一个 running_sum,遇到一条工资就加上去,然后把“当前累计值”写回结果里。
复杂度也很直接: 总共有 n 条记录,排序大概是 O(n log n),遍历累加是 O(n),完全够大部分业务用,除非你们一个月几亿条发薪记录,那时候你再考虑更花活的东西。
用 Python 写一版最实在的
我懒得上什么花里胡哨的库,直接用 list + dict 搞完,代码差不多是这样:
from collections import defaultdict
from typing import List, Dict, Any
defcalc_cumulative_salary(records: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""
records 里每条数据格式类似:
{
"emp_id": 1,
"month": 202401, # 或者 "2024-01" 都行,关键是能比较大小
"salary": 10000,
}
返回结构会多一个字段 cumulative_salary
"""
# 1. 按员工分组
grouped = defaultdict(list)
for r in records:
grouped[r["emp_id"]].append(r)
result = []
for emp_id, emp_records in grouped.items():
# 2. 按月份排序(注意 key 写对)
emp_records.sort(key=lambda x: x["month"])
# 3. 按顺序做前缀和
cum = 0
for r in emp_records:
cum += r["salary"]
# 复制一份,别修改原数据的话就用 copy
new_r = dict(r)
new_r["cumulative_salary"] = cum
result.append(new_r)
# 如果你希望整体也按 emp_id + month 排好再返回,可以再排一次
result.sort(key=lambda x: (x["emp_id"], x["month"]))
return result
if __name__ == "__main__":
data = [
{"emp_id": 1, "month": 202401, "salary": 10000},
{"emp_id": 1, "month": 202403, "salary": 11000},
{"emp_id": 1, "month": 202402, "salary": 12000},
{"emp_id": 2, "month": 202401, "salary": 8000},
{"emp_id": 2, "month": 202403, "salary": 9000},
]
res = calc_cumulative_salary(data)
for row in res:
print(row)
这个跑出来大概是:
{'emp_id': 1, 'month': 202401, 'salary': 10000, 'cumulative_salary': 10000}
{'emp_id': 1, 'month': 202402, 'salary': 12000, 'cumulative_salary': 22000}
{'emp_id': 1, 'month': 202403, 'salary': 11000, 'cumulative_salary': 33000}
{'emp_id': 2, 'month': 202401, 'salary': 8000, 'cumulative_salary': 8000}
{'emp_id': 2, 'month': 202403, 'salary': 9000, 'cumulative_salary': 17000}
看着就挺像一个简单报表的底层数据对吧。
我晚上帮同事看代码的时候,他的几个小坑,顺便给你提一下:
一个是月份的字段,有人喜欢用字符串 "2024-01",有人用整数 202401。不管用哪个,只要排序规则是正确的就行,字符串就直接按字符串排;如果是日期对象比如 datetime.date,也可以,比较运算一样能用。
还有一个是“同一个员工同一个月多条记录”的情况,比如补发工资、绩效后来补算,这种你要提前想好业务规则: 是先合并成一个月一个总金额,再去做累计,还是保留多条记录,每条都算一个“更新后的累计值”。这一块不写清楚,后面业务吵起来你就会被拉进去背锅。
如果你用的是数据库算(比如 SQL 里的窗口函数 sum over partition by 之类),逻辑本质上跟我们这个 Python 前缀和是一样的,只不过把“分组 + 排序 + 累加”交给数据库做而已。
再加一个小变体
有时候领导会说:“我只看今年的累计就行,去年不用算进来。”那你就先把 records 过滤一下:
this_year_records = [r for r in records if str(r["month"]).startswith("2024")]
res = calc_cumulative_salary(this_year_records)
或者再极端一点:按部门 + 员工两层维度累计,那就把 key 换成 (dept_id, emp_id),其他逻辑不变。
行,我先去续个咖啡,你要是还想加个“按天累计”“滑动窗口累计”之类的,我们可以再接着改这个代码。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB