用計算思維“破解”復雜Excel考勤表的自動化之旅

????在我們日常工作中,經常會遇到一些看似簡單卻極其繁瑣的任務。手動處理一份結構復雜的Excel考勤表,就是典型的例子。它充滿了合并單元格、不規則的布局和隱藏的格式陷阱。面對這樣的挑戰,我們是選擇“卷起袖子,日復一日地手動復制粘貼”,還是能換一種更聰明的“思考方式”來一勞永逸地解決問題?
答案當然后者。這種更聰明的思考方式,就是計算思維 (Computational Thinking)
計算思維并非程序員的專利,它是一種人人都可以學習和運用的高級問題解決框架。它包含四大核心原則,能幫助我們將現實世界中的復雜問題,轉化為計算機可以理解并高效執行的解決方案。
今天,我將帶你走一遍我們解決一個真實世界Excel自動化問題的旅程,并深入剖析這四大原則——分解 (Decomposition)模式識別 (Pattern Recognition)抽象 (Abstraction)算法設計 (Algorithm Design)

第一步: 分解 (Decomposition) - 拆解問題

分解,顧名思義,就是將一個復雜的問題,系統性地拆解成一系列更小、更簡單、更易于管理和解決的子問題。它的核心思想是分而治之。如果一個問題太大讓你無從下手,那就把它分開,直到每一小塊都變得清晰可見。

生活實例

想象一下你要策劃一場大型的婚宴。直接面對“大型的婚宴”這個任務可能會讓你頭大。但如果你運用分解思維,你會自然地把它拆解成:

  1. 確定賓客名單:邀請誰?
  2. 選擇場地與時間:在哪里辦?什么時候辦?
  3. 準備食物與飲料:大家吃什么,喝什么?
  4. 策劃活動與娛樂:玩什么?
  5. 發送邀請函與確認:如何通知大家?
    現在,每一個子任務都變得具體、可執行,整個婚宴的策劃也變得井井有條。
本項目應用

我們最初面對的“自動化處理考勤表”就是一個龐然大物。直接動手寫代碼,必然會陷入混亂。因此,我們首先對其進行了分解

  1. 文件讀取與兼容性問題:如何讓Python讀取這個老舊的.xls文件,并理解其內部的合并單元格結構?

  2. 員工定位問題:在一個Sheet內,如何準確地找到每一個員工(張三、李四、王五)的數據區域?在這里插入圖片描述

  3. 數據定位問題:對于每一個員工,如何精確地找到其打卡記錄的起始行?

  4. 數據提取問題:如何從充滿合并單元格的行中,準確地抓取到每一個獨立的打卡時間?

  5. 日期與時間處理問題:如何將Excel的小數時間轉換為HH:MM格式?如何智能處理跨月份的日期?

  6. 數據整合與排序問題:如何將所有零散數據,按照“工號從小到大”的順序,聚合成“每人每天一行”的結構?

  7. 報表生成與格式化問題:如何生成一個帶有兩級復雜表頭的最終.xlsx文件?在這里插入圖片描述
    通過這次分解,原本模糊不清的任務被轉化成了一張清晰的“任務清單”。我們可以逐個攻克這些子問題。

第二步:模式識別 (Pattern Recognition) - 尋找規律

????模式識別是在不同的子問題或數據片段中,發現其共有的、重復出現的規律、趨勢或特征。人類天生就擅長模式識別,而計算機則能將這種能力發揮到極致。識別出模式,是設計高效、可復用解決方案的前提。

生活實例

當你經常去超市買菜時,會發現一些規律

  • 牛奶、面包經常放在一起 → 因為它們常被一起買。
  • 水果的價格通常周末打折 → 你學會了挑選最佳購買時間。
  • 打折標簽的顏色總是紅色 → 一眼就能識別出來哪些是優惠商品。

????久而久之,你不需要每次都從頭到尾逛一遍超市,而是根據這些規律,直接去“該去的貨架”,用更快更省錢的方式完成購物。這種模式識別,就像計算機在處理大量數據時,發現隱藏的共性,從而提高效率。

本項目應用

在分解后的子問題中,我們開始運用模式識別來尋找自動化處理的突破口:

  • 識別出“員工布局模式”:我們觀察到,三個員工的數據塊并非隨機排列,而是以一個**“固定間隔(約15列)”**的模式橫向展開。這個發現讓我們無需為每個員工都去手動定位,而是可以用一個簡單的循環和固定的步長來批量處理。

  • 識別出“數據列模式”:我們發現,每個員工內部的列布局也是高度一致的。無論員工數據從哪一列開始,他的“上午上班”時間總是在其起始列的**“右邊第1格”。這個“相對列偏移量”**的模式是通用的,它構成了我們數據提取算法的核心。

  • 識別出“跨月模式”:我們注意到,當日期從31號突然變為1號時,這標志著一個必然發生的**“月份更替”**模式。這個規律讓我們能夠設計出智能判斷日期并自動更新月份的邏輯。
    模式識別讓我們從繁雜的細節中提煉出了普適的規則,為“一次編寫,到處適用”的自動化方案奠定了基礎。

第三步:抽象 (Abstraction) - 抓住本質

????抽象是計算思維中最具創造力的一步。它要求我們主動忽略那些與當前目標無關的、次要的、令人分心的細節,將問題的核心本質提煉出來,并用一個簡潔的模型或概念來代表它。就像一張地鐵線路圖,它忽略了真實的街道和建筑,只保留了站點和線路這些核心信息。

生活實例

當你開車時,你不需要理解發動機的內燃原理、變速箱的齒輪構造。你只需要知道踩下油門車會加速,轉動方向盤車會轉向。汽車設計師已經為你抽象出了一套簡潔的“接口”(油門、剎車、方向盤),讓你能夠輕松地駕馭一個極其復雜的機械系統。

本項目應用

在我們的項目中,抽象思維的應用是解決最棘手問題的關鍵:

  • 抽象出get_cell_value函數:面對各種不規則的合并單元格,我們沒有陷入“這里是兩格合并,那里是三格合并”的細節泥潭。我們進行了一次抽象:我們不關心一個單元格如何合并,我們只關心它的真實值是什么。

    于是,我們創造了get_cell_value(sheet, row, col)這個“抽象模型”。它像一個黑盒子,封裝了所有處理合并單元格的復雜邏輯。主程序只需調用這個函數,就能得到任何坐標的真實值,而無需關心其底層的合并狀態。這個抽象讓我們成功地忽略了“合并格式”這個最大的噪音

  • 抽象出“內存工作簿”:為了解決.xls.xlsx的兼容性問題,我們抽象出了一個“在內存中進行格式轉換”的概念。主程序無需關心底層的庫調用和數據復制過程,它只需要知道,通過一個簡單的函數調用,就能得到一個可以直接處理的、現代化的工作簿對象。
    抽象,讓我們能夠站在更高的維度思考問題,用簡潔的模型來駕馭底層的復雜性,寫出更清晰、更易于維護的代碼。

第四步:算法設計 (Algorithm Design) - 繪制清晰的行動路線圖

算法設計是將我們通過前三個階段得出的解決方案,轉化為一步步清晰、明確、有序、可執行的指令集。一個好的算法,就像一份完美的菜譜,任何嚴格按照它執行的人(或計算機)都能做出同樣美味的菜肴。

生活實例

宜家家具的組裝說明書就是一份典型的算法。它沒有長篇大論,而是用一系列帶編號的、清晰的圖示和步驟,告訴你:1. 拿出A號螺絲和B號木板;2. 將A擰入B的C孔中;3. …。只要你嚴格遵循這個“算法”,即使你不是木工,也能成功組裝出一件家具。

本項目應用

????我們最終的Python腳本,就是我們為“處理考勤表”這個問題設計的終極算法。它的每一步都清晰無誤:

  1. 初始化:準備好空的容器來存放數據。
  2. 預處理:調用“內存轉換”抽象模型,解決文件格式問題。
  3. 循環與定位
    a. 按照“員工布局模式”,遍歷每個員工塊。
    b. 智能地找到每個員工塊的數據起始行。
  4. 數據提取
    a. 在每個員工塊內逐行讀取。
    b. 運用“跨月模式”和“相對列偏移量模式”。
    c. 循環調用get_cell_value這個“抽象黑盒”,安全地獲取每一個打卡時間。
  5. 后處理:對提取到的所有數據進行排序和聚合。
  6. 生成報表:調用XlsxWriter,按照預設的格式和樣式,手動構建并保存最終的Excel文件。
    這個算法的每一步都直接源于我們之前的分析,它將我們的“思考”固化為了一套計算機可以精確執行的“行動計劃”。

在這里插入圖片描述

結論:計算思維,賦能未來的思考方式

????通過這次真實的旅程,我們可以看到,計算思維并非編程本身,而是一種在編程之前、指導我們如何系統性地思考和解決問題的強大框架。它是一套可以被任何人學習和應用的“思維工具箱”。當你再遇到一個令人頭疼的、復雜的、重復性的任務時,無論是在工作中還是生活中,不妨先停下來,泡杯咖啡,嘗試用分解、模式識別、抽象、算法設計這四個“鏡頭”去審視它。你可能會驚奇地發現,任何看似堅不可摧的復雜問題,都可以在這種系統性的思考方式下,被你優雅地、一步步地“攻破”。

源碼

# 導入所有必需的“工具包”,這是我們實現算法的基礎。
import xlrd  # 用于讀取老舊的.xls文件格式。
import openpyxl  # 用于處理現代的.xlsx文件格式,特別是其強大的合并單元格處理能力。
import re  # 用于正則表達式,從字符串中精確提取日期范圍等模式。
from datetime import datetime, time  # 用于處理日期和時間對象。
import pandas as pd  # 用于最終的數據整合與強大的Excel寫入功能。
from collections import defaultdict  # 用于創建一個方便的數據聚合結構。# --- ABSTRACTION (抽象) 階段 ---
# 我們將解決一個復雜問題的具體方法,封裝成一個獨立的、可復用的“黑盒子”。
# 主程序只需要知道這個函數能做什么(它的功能),而不需要關心它內部如何實現(它的細節)。def convert_xls_to_xlsx_in_memory(xls_path):"""【抽象】將 .xls 文件轉換為內存中的 .xlsx 對象。這是一個核心的抽象,它將“解決文件格式兼容性”這個復雜的子問題,封裝成了一個簡單的函數調用。主程序不再需要關心底層的格式轉換細節。"""# DECOMPOSITION (分解): 這個問題被分解為三個小步驟:# 1. 打開.xls文件。# 2. 創建一個空的.xlsx對象。# 3. 逐一復制數據和格式。xls_book = xlrd.open_workbook(xls_path, formatting_info=True)xlsx_book = openpyxl.Workbook()for sheet_index in range(xls_book.nsheets):xls_sheet = xls_book.sheet_by_index(sheet_index)if sheet_index == 0:xlsx_sheet = xlsx_book.activexlsx_sheet.title = xls_sheet.nameelse:xlsx_sheet = xlsx_book.create_sheet(title=xls_sheet.name)# 復制單元格的值for row in range(xls_sheet.nrows):for col in range(xls_sheet.ncols):xlsx_sheet.cell(row=row + 1, column=col + 1).value = xls_sheet.cell_value(row, col)# 復制合并單元格信息,這是確保格式正確的關鍵。for crange in xls_sheet.merged_cells:rlo, rhi, clo, chi = crangexlsx_sheet.merge_cells(start_row=rlo + 1, start_column=clo + 1, end_row=rhi, end_column=chi)# 清理openpyxl默認創建的不需要的'Sheet'。if 'Sheet' in xlsx_book.sheetnames and len(xlsx_book.sheetnames) > 1:del xlsx_book['Sheet']return xlsx_bookdef get_cell_value(sheet, row, col):"""【抽象】安全地獲取單元格的值,能自動處理合并單元格。這是整個項目中最重要的一個抽象。我們忽略了“兩格合并還是三格合并”的復雜細節,只關注“獲取這個坐標的真實值”這一核心需求。這個函數封裝了所有與合并單元格相關的復雜邏輯。"""if row > sheet.max_row or col > sheet.max_column: return Nonecell = sheet.cell(row=row, column=col)# ALGORITHM (算法): 這里有一個清晰的算法來處理合并單元格。# 1. 檢查當前單元格是否在某個合并區域內。# 2. 如果是,則找到該區域的起始單元格并返回其值。# 3. 如果不是,則直接返回當前單元格的值。for merged_range in sheet.merged_cells.ranges:if cell.coordinate in merged_range:return merged_range.start_cell.valuereturn cell.valuedef parse_day_weekday(value_str):"""【抽象】從'13 三'這樣的字符串中解析出日期和星期。這個函數抽象了“從混合字符串中分離信息”的任務。"""if not value_str: return None, None# PATTERN RECOGNITION (模式識別): 我們識別出這類字符串的模式總是 "數字 + 空格 + 字符"。# 基于這個模式,我們使用 split() 方法進行分割。parts = str(value_str).strip().split()return (parts[0] if parts else None, parts[1] if len(parts) > 1 else None)def excel_time_to_hhmm(excel_time):"""【抽象】將Excel的小數或時間對象轉換為 HH:MM 格式的字符串。封裝了時間格式轉換的邏輯,主程序無需關心Excel內部如何存儲時間。"""if isinstance(excel_time, (datetime, time)):return excel_time.strftime('%H:%M')if isinstance(excel_time, (float, int)):total_seconds = int(round(excel_time * 24 * 3600))hours = total_seconds // 3600minutes = (total_seconds % 3600) // 60return f"{hours:02d}:{minutes:02d}"if isinstance(excel_time, str):return excel_timereturn Nonedef find_data_start_row(sheet, start_col):"""【抽象】智能查找數據記錄的起始行。這個函數抽象了“定位數據從哪里開始”的問題,避免了硬編碼行號帶來的風險。"""# PATTERN RECOGNITION (模式識別): 我們識別出數據記錄的上方必然存在一個包含“日 期”和“上班/上午”的表頭行。# 這個模式是定位的“路標”。for r in range(10, 16):header_val = str(get_cell_value(sheet, r, start_col) or "")next_header_val = str(get_cell_value(sheet, r, start_col + 1) or "")is_date_header = "日" in header_val and "期" in header_valis_time_header = "上午" in next_header_val or "上班" in next_header_valif is_date_header and is_time_header:# ALGORITHM (算法): 我們的算法是:數據起始行 = 標題行 + 2。return r + 2print(f"  -> 警告:未能自動定位到數據起始行,將使用默認值14。")return 14# --- ALGORITHM DESIGN (算法設計) 階段 ---
# 這是整個解決方案的“總指揮部”或“菜譜”。
# 它清晰地定義了從頭到尾的每一個步驟,并調用我們之前抽象好的函數來完成具體的子任務。def process_attendance_final_solution(input_filename="考勤報表.xls"):"""終極版:這是解決整個考勤表問題的核心算法。"""# DECOMPOSITION (分解): 整個過程被分解為預處理、數據提取、后處理和報表生成四個主要步驟。# === 步驟 1: 預處理 ===try:print("檢測到 .xls 文件,正在進行內存轉換...")# 調用我們抽象好的函數,解決文件兼容性問題。workbook = convert_xls_to_xlsx_in_memory(input_filename)print("轉換成功!開始處理數據...")except FileNotFoundError:print(f"錯誤:文件 '{input_filename}' 未找到。")returnexcept Exception as e:print(f"讀取或轉換Excel文件時出錯: {e}")return# === 步驟 2: 數據提取 ===if len(workbook.sheetnames) < 3:print("錯誤:文件中的Sheet數量不足3個,無法跳過前兩個總覽表。")returnsheets_to_process = workbook.sheetnames[2:]print(f"將要處理的Sheet列表: {sheets_to_process}")daily_records = defaultdict(dict)date_range_for_filename = None# PATTERN RECOGNITION (模式識別): 識別出員工數據塊總是從這幾列開始的模式。employee_start_cols = [1, 16, 31]# 外層循環: 遍歷所有需要處理的Sheet。for sheet_name in sheets_to_process:print(f"\n--- 正在提取Sheet: '{sheet_name}' ---")sheet = workbook[sheet_name]# 中層循環: 遍歷每個Sheet內的員工塊。for start_col in employee_start_cols:name = get_cell_value(sheet, 4, start_col + 11)if name is None or str(name).strip() == "": continueemp_id_val = get_cell_value(sheet, 5, start_col + 11)emp_id = str(int(float(emp_id_val))) if emp_id_val is not None else ""print(f"找到員工: {name} (工號: {emp_id})")# 調用抽象函數,智能定位數據從哪一行開始讀取。data_start_row = find_data_start_row(sheet, start_col)print(f"  -> 數據將從第 {data_start_row} 行開始讀取。")if date_range_for_filename is None:date_cell_val = str(get_cell_value(sheet, 5, start_col + 1))match = re.search(r'(\d{4}-\d{2}-\d{2})~(\d{4}-\d{2}-\d{2})', date_cell_val)if match: date_range_for_filename = match.group(0)start_date_str = (date_range_for_filename or "2025-01-01~2025-01-01").split('~')[0]start_date = datetime.strptime(start_date_str, '%Y-%m-%d')current_year, current_month, last_day = start_date.year, start_date.month, 0# 內層循環: 逐行提取打卡記錄。for r in range(data_start_row, sheet.max_row + 1):day_str, weekday = parse_day_weekday(get_cell_value(sheet, r, start_col))if day_str is None: continuetry:day = int(float(day_str))except (ValueError, TypeError):continue# PATTERN RECOGNITION (模式識別): 識別并應用“跨月份”的模式。if day < last_day:current_month += 1if current_month > 12: current_month, current_year = 1, current_year + 1full_date_str, last_day = f"{current_year}-{current_month:02d}-{day:02d}", dayrecord_key = (name, emp_id, full_date_str, weekday)# PATTERN RECOGNITION (模式識別): 應用“相對列偏移量”模式來定位各個時間點。# ABSTRACTION (抽象): 每次都調用 get_cell_value 和 excel_time_to_hhmm 這兩個“黑盒子”。times = {'上午上班': excel_time_to_hhmm(get_cell_value(sheet, r, start_col + 1)),'上午下班': excel_time_to_hhmm(get_cell_value(sheet, r, start_col + 3)),'下午上班': excel_time_to_hhmm(get_cell_value(sheet, r, start_col + 7)),'下午下班': excel_time_to_hhmm(get_cell_value(sheet, r, start_col + 9)),'加班簽到': excel_time_to_hhmm(get_cell_value(sheet, r, start_col + 11)),'加班簽退': excel_time_to_hhmm(get_cell_value(sheet, r, start_col + 12)),}for event_type, event_time in times.items():if event_time:daily_records[record_key][event_type] = event_time# === 步驟 3: 后處理 (排序與聚合) ===if not daily_records:print("\n未能提取到任何有效的考勤記錄。")returnprint("\n--- 所有數據提取完畢,正在排序并生成最終報表... ---")final_rows = []# ALGORITHM (算法): 定義清晰的排序規則:先按工號(轉為數字),再按日期。sorted_records = sorted(daily_records.items(), key=lambda item: (int(item[0][1]), item[0][2]))for (name, emp_id, date, weekday), times in sorted_records:final_rows.append({"姓名": name, "工號": emp_id, "日期": date, "星期": weekday,"上午上班": times.get('上午上班'), "上午下班": times.get('上午下班'),"下午上班": times.get('下午上班'), "下午下班": times.get('下午下班'),"加班簽到": times.get('加班簽到'), "加班簽退": times.get('加班簽退'),})# === 步驟 4: 報表生成 ===df = pd.DataFrame(final_rows)output_filename = f"員工考勤表_最終版_{date_range_for_filename or ''}.xlsx"try:# ALGORITHM (算法): 這是一個手動構建復雜Excel文件的清晰算法。# 1. 創建一個writer對象。# 2. 將純數據寫入(從第3行開始)。# 3. 手動寫入并合并兩級表頭。# 4. 調整格式。# 5. 保存并關閉。writer = pd.ExcelWriter(output_filename, engine='xlsxwriter')df.to_excel(writer, sheet_name='考勤匯總', index=False, header=False, startrow=2)workbook = writer.bookworksheet = writer.sheets['考勤匯總']header_format = workbook.add_format({'bold': True, 'align': 'center', 'valign': 'vcenter', 'border': 1})worksheet.write('A2', '姓名', header_format)worksheet.write('B2', '工號', header_format)worksheet.write('C2', '日期', header_format)worksheet.write('D2', '星期', header_format)worksheet.write('E2', '上班', header_format)worksheet.write('F2', '下班', header_format)worksheet.write('G2', '上班', header_format)worksheet.write('H2', '下班', header_format)worksheet.write('I2', '簽到', header_format)worksheet.write('J2', '簽退', header_format)worksheet.merge_range('A1:D1', '', header_format)worksheet.merge_range('E1:F1', '上午', header_format)worksheet.merge_range('G1:H1', '下午', header_format)worksheet.merge_range('I1:J1', '加班', header_format)worksheet.set_column('A:A', 10)worksheet.set_column('B:B', 8)worksheet.set_column('C:C', 12)worksheet.set_column('D:D', 8)worksheet.set_column('E:J', 10)writer.close()print(f"\n處理成功!\n匯總報表已保存為: '{output_filename}'")except Exception as e:print(f"保存最終文件時出錯: {e}")# 程序的入口點,算法從這里開始執行。
if __name__ == "__main__":process_attendance_final_solution(input_filename="考勤報表.xls")

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98484.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98484.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98484.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PAT 1006 Sign In and Sign Out

1006 Sign In and Sign Out分數 25作者 CHEN, Yue單位 浙江大學At the beginning of every day, the first person who signs in the computer room will unlock the door, and the last one who signs out will lock the door. Given the records of signing ins and outs, yo…

【git】首次clone的使用采用-b指定了分支,還使用了--depth=1 后續在這個基礎上拉取所有的分支代碼方法

要解決當前問題&#xff08;從淺克隆轉換為完整克隆并獲取所有分支&#xff09;&#xff0c;請按照以下步驟操作&#xff1a; 步驟 1&#xff1a;檢查當前遠程地址 首先確認遠程倉庫地址是否正確&#xff1a; git remote -v步驟 2&#xff1a;修改遠程配置以獲取所有分支 默認淺…

蘿卜切丁機 機構筆記

蘿卜切丁機_STEP_模型圖紙免費下載 – 懶石網 機械工程師設計手冊 1是傳送帶 2是曲柄滑塊機構&#xff1f; 擠壓動作

多張圖片生成視頻模型技術深度解析

多張圖片生成視頻模型測試相比純文本輸入&#xff0c;有視覺參考約束的生成通常質量更穩定&#xff0c;細節更豐富 1. 技術原理和工作機制 多張圖片生成視頻模型是一種先進的AI技術&#xff0c;能夠接收多張輸入圖像&#xff0c;理解場景變化關系&#xff0c;并合成具有時間連…

中電金信:AI重構測試體系·智能化時代的軟件工程新范式

AI技術的迅猛發展正加速推動軟件工程3.0時代的到來&#xff0c;深刻地重塑了測試行業的運作邏輯&#xff0c;推動測試角色從“后置保障”轉變為“核心驅動力”。在大模型技術的助力下&#xff0c;測試質量和效能將顯著提升。9月5日至6日&#xff0c;Gtest2025全球軟件測試技術峰…

100、23種設計模式之適配器模式(9/23)

適配器模式&#xff08;Adapter Pattern&#xff09; 是一種結構型設計模式&#xff0c;它允許將不兼容的接口轉換為客戶端期望的接口&#xff0c;使原本由于接口不兼容而不能一起工作的類可以協同工作。 一、核心思想 將一個類的接口轉換成客戶期望的另一個接口使原本因接口不…

線上環境CPU使用率飆升,如何排查

線上環境CPU使用率飆升&#xff0c;如何排查 1.CPU飆升的常見原因 1. 代碼層面問題 死循環&#xff1a;錯誤的循環條件導致無限循環遞歸過深&#xff1a;沒有正確的終止條件算法效率低&#xff1a;O(n)或更高時間復雜度的算法處理大數據集頻繁GC&#xff1a;內存泄漏導致頻繁垃…

《sklearn機器學習——特征提取》

在 sklearn.feature_extraction 模塊中&#xff0c;DictVectorizer 是從字典&#xff08;dict&#xff09;中加載和提取特征的核心工具。它主要用于將包含特征名稱和值的 Python 字典列表轉換為機器學習算法所需的數值型數組或稀疏矩陣。 這種方法在處理結構化數據&#xff08;…

IEEE出版,限時早鳥優惠!|2025年智能制造、機器人與自動化國際學術會議 (IMRA 2025)

2025年智能制造、機器人與自動化國際學術會議 (IMRA2025)2025 International Conference on Intelligent Manufacturing, Robotics, and Automation中國?湛江2025年11月14日-2025年11月16日IMRA2025權威出版大咖云集穩定檢索智能制造、人工智能、機器人、物聯網&#xff08;Io…

C# 基于halcon的視覺工作流-章30-圓圓距離測量

C# 基于halcon的視覺工作流-章30-圓圓距離測量 本章目標&#xff1a; 一、利用圓卡尺找兩圓心&#xff1b; 二、distance_pp算子計算兩圓點距離&#xff1b; 三、匹配批量計算&#xff1b;本章是在章23-圓查找的基礎上進行測量使用&#xff0c;圓查找知識請閱讀章23&#xff0c…

java設計模式二、工廠

概述 工廠方法模式是一種常用的創建型設計模式&#xff0c;它通過將對象的創建過程封裝在工廠類中&#xff0c;實現了創建與使用的分離。這種模式不僅提高了代碼的復用性&#xff0c;還增強了系統的靈活性和可擴展性。本文將詳細介紹工廠方法模式的三種形式&#xff1a;簡單工廠…

Ubuntu 24.04 中 nvm 安裝 Node 權限問題解決

個人博客地址&#xff1a;Ubuntu 24.04 中 nvm 安裝 Node 權限問題解決 | 一張假鈔的真實世界 參考nvm的一個issue&#xff1a;https://github.com/nvm-sh/nvm/issues/3363 異常信息如下&#xff1a; $ nvm install 22 Downloading and installing node v22.19.0... Download…

Java面試-線程安全篇

一、synchronized關鍵字&#xff1a; 基本使用與作用&#xff1a;通過搶票代碼示例&#xff0c;展示了synchronized作為對象鎖&#xff0c;可避免多線程超賣或搶到同一張票問題&#xff0c;保證代碼原子性&#xff0c;同一時刻只有一個線程獲得鎖&#xff0c;其他線程阻塞。底層…

R 語言科研繪圖 --- 其他繪圖-匯總2

在發表科研論文的過程中&#xff0c;科研繪圖是必不可少的&#xff0c;一張好看的圖形會是文章很大的加分項。 為了便于使用&#xff0c;本系列文章介紹的所有繪圖都已收錄到了 sciRplot 項目中&#xff0c;獲取方式&#xff1a; R 語言科研繪圖模板 --- sciRplothttps://mp.…

【數學建模學習筆記】啟發式算法:粒子群算法

零基礎小白看懂粒子群優化算法&#xff08;PSO&#xff09;一、什么是粒子群優化算法&#xff1f;簡單說&#xff0c;粒子群優化算法&#xff08;PSO&#xff09;是一種模擬鳥群 / 魚群覓食的智能算法。想象一群鳥在找食物&#xff1a;每只鳥&#xff08;叫 “粒子”&#xff0…

【Gitlab】Ubuntu 20.04服務器部署Gitlab

寫一個 適用于 Ubuntu 20.04/22.04 的 GitLab 一鍵部署腳本&#xff0c;包括&#xff1a;安裝依賴安裝 GitLab CE配置公網 IP 或域名自動開啟 HTTPS&#xff08;Let’s Encrypt&#xff09;配置防火墻下面是完整腳本&#xff1a;#!/bin/bash# # GitLab 一鍵安裝腳本 # # 1. 檢…

Android 15重磅升級:16KB內存頁機制詳解與適配指南

一、背景隨著Android硬件架構的持續演進&#xff0c;新一代設備開始采用16KB內存頁&#xff08;Page Size&#xff09;機制&#xff0c;逐步替代傳統的4KB內存頁設計。此項底層變更對應用兼容性產生直接影響&#xff0c;特別是對依賴Native層庫、JNI接口或自定義內存管理模塊的…

Mybatis-8 動態SQL

動態SQL-官方文檔 文檔地址 動態 SQL_MyBatis中文網 為什么需要動態SQL 1、動態SQL是MyBatis的強大特性之一 2、使用JDBC或其它類似的框架&#xff0c;根據不同條件拼接SQL語句非常麻煩&#xff0c;例如拼接時要確保不能忘記添加必要的空格&#xff0c;還要注意去掉列表最后一…

PySpark數據輸入

PySpark數據輸入 1.理解RDD對象 2.掌握PySpark數據輸入的2種方法 RDD對象 PySpark支持多種數據的輸入&#xff0c;在輸入完成后&#xff0c;都會得到一個&#xff1a;RDD類的對象 RDD全稱為&#xff1a;彈性分布式數據集&#xff08;Resilient Distributed Datasets&#xff09…

【系統架構設計(16)】軟件架構設計二:軟件架構風格:構建系統的設計模式與選擇指南

文章目錄一、核心思想二、數據流風格&#xff1a;以數據流動為核心的處理模式三、調用返回風格&#xff1a;基于程序調用的層次化組織四、獨立構件風格&#xff1a;基于事件驅動的松耦合架構五、虛擬機風格&#xff1a;提供抽象執行環境的架構模式六、倉庫風格&#xff1a;以數…