一位支援工程師曾經問我為什麼四十名客戶兩次收到續約電子郵件。答案花了一個小時才找到,而且完全很平凡:活動清單是透過將一個匯出項貼到另一個匯出項下來組裝的,兩個匯出項中都存在四十個地址。沒有人檢查過,因為檢查意味著要么盯著兩千行,要么寫一個 VLOOKUP 團隊的一半沒有't信任。所以沒有人檢查,同樣的四十個人兩次被告知他們的卡即將被扣款。
這就是這個問題的形式。協調兩個清單是任何人對資料最常見的事情之一,它'無聊到人們要么跳過它,要么做得很糟糕。本能通常是找到一個差異工具,將兩個列表貼上進去,然後瞇著眼睛看彩色輸出 - 這會立即失敗,因為差異回答了您沒有的問題't 詢問。或者您轉到電子表格並開始組裝 MATCH/COUNTIF 公式,有效,但需要十分鐘並產生一個工件 you'永遠不會重複使用。
您實際想要的操作有一個名稱,它'比任何工具都舊:設定算術。交叉點、差異、聯合。我建立 [toolz。dev](/並放置一個基於瀏覽器的 列出比較工具 但本指南是關於下面的概念 - 為什麼應該忽略順序,什麼情況會悄悄破裂,以及如何在這個問題和差異之間做出選擇。
TL;DR: 要比較兩個列表,請將每個列表視為無序集併計算交叉點(兩個列表中的項目)、兩個差異(僅在 A 中的項目,僅在 B 中的項目)以及每個列表中的重複項。完全忽略順序 - 行差異是錯誤的工具,因為它's 位置,因此重新排序列表幾乎會改變每一行。對電子郵件等標識符進行折疊,但保留輸出中的原始文本,在比較之前修剪空白,並在瀏覽器中執行此操作,因為人們協調的列表通常是客戶資料。
比較兩個清單實際上可以回答哪些問題?
一旦看到命名的操作,形狀就會變得顯而易見。給定列表 A 和列表 B:
- 交叉口- 什麼'兩者都有?哪些訂閱者也是付費客戶。上個月的哪一個' SKU 仍在本月' 的目錄中。
- A 減 B- 什麼'僅在 A? CRM 中的哪些使用者從未進入計費階段。哪些檔案存在於本機但不存在於伺服器上。
- B 減去 A- 什麼'僅在 B?另一個方向上也有同樣的問題,它's a 不同的 問題。帳單缺失和 CRM 缺失是兩個不同的錯誤,有兩個不同的原因。
- 對稱差異-什麼'恰好在一個清單中?兩種差異的結合:所有不匹配的東西,無論方向如何。這是"什麼'不同步?"問題。
- 聯盟- 任一清單中的所有內容,已刪除重複。合併,正確完成。
- 清單中的重複項- 什麼'僅在 A 內重複?這個根本就是't比較,但是它'總是你需要的問題,因為它'是什麼導致了雙重發送和雙重計費。
最後一個值得分開。交叉列表匹配和列表內複製是獨立的:位址可以在 A 中出現兩次 和 也出現在 B 中。僅報告交叉清單結果的工具會錯過需要花錢的故障。
這裡的所有內容都直接映射到您已經從 SQL - 知道的操作 INTERSECT, EXCEPT, UNION- 以及電子表格公式。專用工具的價值是 #39;t 它做了一些你可以做的事情 't; '所有六個答案都從一個貼上顯示出來,而不是六個不同的公式。
為什麼 diff 工具比較清單的選擇是錯誤的?
這是我看到最多的錯誤,它'值得精確,因為 "比較兩個列表和引用;和&引用;差異兩個文件和引用;聽起來像是同義詞。
差異是位置的。 差異演算法計算最小編輯腳本 - 將一個序列轉換為另一個序列的最短插入和刪除序列。 That'是原始碼和散文的正確模型,其中第 39 行後面的第 40 行是 有意義的. 移動函數,差異會正確報告您移動了函數。
列表沒有有意義的順序。 CRM 匯出中的第 300 行與帳單匯出中的第 300 行沒有任何關係。他們'是兩袋物品,無論資料庫傳回的順序如何,它們都會被寫下來。
將無序資料輸入位置演算法,您就會收到雜訊。取兩個內容相同的列表,對其中一個進行排序,然後進行差異:
List A List B
alice bob
bob alice
carol carol
A diff 報告稱 alice 被刪除並重新添加,或者那個 bob 移動 - 有些攪動與兩者的排序方式成正比。正確答案是 什麼都沒有改變. 每個項目都在兩個清單中。集合相等。差異可以't這麼說,因為它是't詢問會員資格。
比較表,因為尋找這兩種工具的人的想法確實重疊:
| 列出比較 | 文字差異 | |
|---|---|---|
| 模型 | 無序的項目集 | 有序的行序列 |
| 訂單很重要嗎? | 不 - 自由重新排序,結果相同 | 是的 - 重新排序顯示為更改 |
| 答案 | 會員資格:兩者中,只有 A、只有 B、重複 | 編輯:插入/刪除什麼以將 A 轉換為 B |
| 重複的項目 | 作為一個團體明確報告 | 只是更多的線條 |
| 好 | 協調出口、電子郵件清單、ID、SKU、庫存 | 原始碼、散文、設定檔、任何位置意義的地方 |
| 不好的 | 比較文件的兩個版本 | 任何排序順序為任意的清單 |
規則: 如果您'對清單的排序方式同樣滿意,您想要一個固定的比較。 如果重新排序線路是一個真正值得報告的變化,那麼您想要 文字差異檢查器。 對於具有嵌套而不是平線的結構化數據,兩者都不適用 - that'這是什麼 JSON 差異 是 for,因為它按關鍵路徑而不是按行或按成員資格進行比較。
案例敏感性該如何發揮作用?
這是人們在預設情況下離開然後悄悄出錯的選項,所以它'值得思考一次。
不區分大小寫的配對是大多數人比較的資料的正確預設值。電子郵件地址、使用者名稱、網域名稱、產品代碼、國家/地區代碼 - 這些在實踐中通常不區分大小寫,並且 [email protected] 和 [email protected] 在每個重要的系統中都是同一個人。
那裡'這裡有一個迂腐的警告'值得知道,因為它'偶爾承重:每 RFC 5321,電子郵件地址的網域部分不區分大小寫,但是 本地 部分 - 之前的一切 @- 正式區分大小寫,由接收郵件伺服器解釋。所以 [email protected] 和 [email protected] 原則上可以是不同的郵箱。實際上,基本上每個主要提供者都將它們視為相同,如果您'正在去複製郵件列表,您絕對應該折疊外殼。但如果您'重新偵錯為什麼一個特定位址會反彈,那麼'這就是重要的細節。
案例-敏感的 對於任何包含 case 資訊的事物,匹配都是正確的:Linux 檔案路徑、base64 字串、雜湊值、JWT 令牌、API 金鑰、Git SHA、大多數程式識別碼。密碼雜湊清單上的折疊案例將合併不同的值並給您一個自信的錯誤答案。
實施細節比選項本身更重要: 折疊外殼進行匹配,但顯示原始文字。 如果你貼 [email protected] 該工具告訴您 '在兩個列表中,它都應該返回 [email protected]- 不是 [email protected]. 降低輸出大小會在過程中默默地損壞您的數據,並且由於通常的下一步是將結果貼到其他地方,因此損壞會傳播。該工具將每個項目的首見形式保留在幕後折疊的鑰匙上並匹配,因此結果就是您放入的內容。
空白值得同樣的待遇,卻不被考慮。從電子表格中複製一欄,或像這樣分割一行 a, b, c 在逗號上,您會得到帶有前導空格的項目。 [email protected] 和 [email protected] 是不同的字串和相同的位址。因此,修剪預設為開啟,並且 's 選項 you'd 在實際使用後約三十秒內通知遺失。
我應該使用什麼分隔符號?
預設情況下,每行一個項目,這就是您貼上電子表格列的內容- 剪貼簿會傳遞換行符分隔的值,因此來自Excel、Google Sheets 或CSV 匯出的一列電子郵件會立即加入,無需重新格式化。
其他分隔符號涵蓋已經內聯到達的資料。單一 CSV 行或複製數組的逗號。用於 Outlook 的分號和用於位址清單的舊 Windows 約定的分號。 shell 輸出的空間 - ls, git diff --name-only 管道通過 tr,任何空間界定的東西。從電子表格水平而不是垂直貼上的一行的選項卡。
需要注意的一件事是:逗號上的分裂 不是 CSV 解析。真實的 CSV 欄位可以在引號內包含逗號,而簡單的分割將會撕裂 "Smith, Jane" 分為兩個項目。如果您'從帶有引用欄位的真實 CSV 檔案中提取一列,請將其運行到 CSV 檢視器 首先 - 它實現了實際的 RFC 4180 引用規則 - 然後複製您想要的列。對於沒有嵌入逗號的電子郵件或 ID 的平面列表,分割是可以的,這不會出現 't。
預設情況下,空條目會被刪除,因為它們'幾乎總是偽影:貼上末尾的尾隨換行符、電子表格中的空白行、雙逗號。空字串是 't 您實際關心的任何清單中的項目。如果您'存在此選項;專門在匯出中尋找空白行,這是一個真實但不常見的事情。
比較規模如何?
比較兩個清單的簡單方法是一個嵌套循環:對於 A 中的每個項目,掃描所有 B。That's O (n×m),以及 it'對於一百個項目罰款,五萬個項目無法使用,其中 you'正在進行 25 億個字串比較。
正確的方法將每個清單索引到由比較鍵(項目的折疊、修剪形式)鍵控的雜湊圖中,該值是第一個看到的原始值。建立每個索引都是一次線性傳遞。然後每個問題都變成每個項目的恆定時間查找:這是 B' 中的鍵嗎?s 地圖?整個比較是O(n+m),這意味著每邊兩萬個項目是四萬個雜湊運算,並且完成速度比瀏覽器重新繪製的速度還要快。
相同的索引免費提供重複項。建立它時每個鍵的計數出現次數;任何計數高於 1 的鍵都會在該清單中重複。沒有第二次通過,沒有額外的結構。
實際上,上限是 't 比較 - it's 瀏覽器將五萬行的結果組渲染到文字區域。無論如何,算術都以毫秒為單位結束。如果您'通常要在腳本而不是選項卡中協調這麼大的列表,並且上面的演算法在任何語言中大約是十行。
排序值得注意。預設情況下,結果會自然排序,這意味著數字感知: item2 之前 item10,不是在它之後。簡單的字典排序放置 item10 首先是因為 1 < 2 逐個字符,在掃描 ID 或版本化名稱時,字串比較字母是正確的,而每個人類期望都是錯誤的。關閉排序,您就會得到插入順序 - 項目按照它們首先出現在 A 中的順序排列,然後是 B - 當原始順序編碼新近度之類的東西時,這有時是您想要的。
這在實踐中是什麼樣子?
I've 實際使用此的四種場景,每種場景都對應到不同的結果組。
在發送之前清理郵件清單。 貼上新清單和先前發送的清單。 僅在A 是誰已經聯繫了 ' - 那是 ' 是您的發送清單。 兩者皆有 是誰'會得到一個副本。 A 中的重複項 是本頁頂部故事中的四十個人。該檢查需要 15 秒,它'這將為支援工程師節省一個小時。
協調兩個系統。 將使用者電子郵件從 CRM 匯出到 A,從計費匯出到 B。 僅在A 已註冊但從未計費; 僅在 B 中 是從 CRM 計費但缺少的。這是兩個不同的錯誤。第一個可能是損壞的網路掛鉤,第二個可能是流程之外有人開立的手動發票。單一&引用;這些清單不同&引用;答案會完全掩蓋這一點,這正是兩個方向單獨報告的原因。
庫存和目錄漂移。 上個月'與本月相比 SKU 出口's。 僅在A 已停產, 僅在 B 中 是新的, 兩者皆有 被結轉。這裡的排序很重要 - 匯出以不同的順序來自不同的系統,差異會報告整個文件已更改。
部署健全性檢查。 暫存文件與生產文件,來自兩個 ls 輸出貼有空間分隔符號。 僅在A 是已經發貨的'。
這四個問題的模式:有用的答案幾乎從來都不是"清單不同。&引用;它's 哪個 項目,在 哪個 方向 - 這正是集合運算給您的方向,以及相似度分數或差異摘要所沒有的方向't。
我的清單上傳到任何地方嗎?
不,想想你和#39;d 貼到這樣的工具裡。
It'是訂戶匯出。客戶電子郵件清單。員工 ID。許可證密鑰。帳號。人們核對的清單本質上接近組織保存的最敏感的資料 - 您不知道'不核對任何列表,您核對列表 人. 和&引用;讓我將這 2000 封客戶電子郵件貼上到一個隨機網站中以檢查重疊和引用;這句話應該讓你冷靜下來,因為在許多司法管轄區,#39;是您剛剛在沒有合約的情況下建立的處理器關係。
There'沒有理由讓這個計算觸及網路。它'字串上的雜湊映射 - 幾百行無依賴性的 TypeScript。 toolz。dev 上的工具完全在您的標籤中運行;這些清單是瀏覽器中的 JavaScript 字串'記憶體,它們永遠不會離開它。沒有任何內容被上傳、記錄或儲存。按照您的方式驗證'd 驗證任何此類聲明:開啟網路標籤並點擊比較,或關閉您的 wifi 並觀看它繼續工作。 I'已經寫了更多關於為什麼這個架構對於此類資料很重要 為什麼基於瀏覽器的工具會擊敗伺服器端的工具.
問號
如何比較兩個清單以找到它們的共同點?
將一個清單貼上到清單 A,另一個清單貼上到清單 B,然後按比較。 &引用;在兩者中&引用;群組是交集 - 兩個清單中存在的每個項目。您可以自行複製該群組,將其下載為文字文件,或使用複製報告立即匯出每個群組。訂單不't 很重要,因此清單 don't 需要以相同的方式排序。
如何找到一個列表但不在一個列表中而不是另一個列表中的項目?
& 引用;僅在 A" 中;和"僅在 B" 中;群組回答這個問題,並且它們'是故意分開的。僅在 A 中保存清單 B 中缺失的項目;僅在 B 中保存清單 A 中缺失的項目。這些通常是具有不同原因的不同問題 - 缺少計費和缺少 CRM aren't 相同的錯誤 - 因此將它們折疊成一個答案會失去您需要的資訊。 "唯一&引用;如果您想要對稱差,群組會將兩者組合在一起。
它可以在單一列表中找到重複項嗎?
是的。 A 中的重複項和 B 中的重複項列出了該清單中多次出現的每個不同項目。這與交叉列表匹配無關,因此一個項目既可以在 A 中複製,也可以在 B 中出現。It's 通常是實踐中最重要的檢查,因為列表內重複是導致重複電子郵件和重複計費的原因。
大寫會影響比較嗎?
僅當您願意時。預設情況下區分大小寫的匹配會關閉,因此 [email protected] 和 [email protected] 被視為一項 - 輸出保留您貼上的任何形式,而不是降低資料大小。開啟 case 具有意義的值:Linux 路徑、base64 字串、雜湊值、API 金鑰、Git SHA。
什麼'這是與文字差異工具之間的差異嗎?
diff 是位置性的:它將第 1 行與第 1 行進行比較,並計算將一個序列轉換為另一個序列所需的編輯,因此重新排序清單會使幾乎每一行看起來都發生變化。此工具完全忽略順序,僅詢問每一側是否存在項目。使用 diff 表示程式碼和散文,其中位置是意義的;使用 list compare 來協調排序順序任意的匯出。
我可以比較以逗號分隔的列表而不是新行嗎?
是的 - 將分隔符號切換為逗號、分號、空格或製表符。預設情況下,每個項目周圍的空白都會被修剪,因此 a, b, c 分成三個乾淨的項目。一個注意事項:在逗號上分割是't 真實的 CSV 解析,因此如果您的資料引用了包含逗號的字段,請先使用正確的 CSV 工具提取該列。
它可以處理多少個項目?
比較將每個清單索引到雜湊圖中,並在線性時間內運行,而不是使用嵌套循環,因此每一側的數萬個項目在毫秒內完成。實用的上限是您的瀏覽器在頁面中渲染一個非常大的結果組,而不是比較本身。
我的清單上傳到任何地方嗎?
不。所有解析和比較都以 JavaScript 的形式在瀏覽器中進行 - 任何內容都不會傳輸、記錄或儲存。這裡比大多數工具更重要,因為人們協調的清單通常是客戶電子郵件、員工 ID 或許可證金鑰。比較時請注意網路選項卡,或離線並繼續工作。
相關工具: 文字差異檢查器 當秩序和位置很重要時, JSON 差異 對於結構化數據, CSV 檢視器 用於從真實 CSV 中提取列,以及 字計數器 為了快速計數。進一步閱讀: 為什麼基於瀏覽器的工具會擊敗伺服器端的工具 和 web 開發人員's 工具包.



