מהנדס תמיכה שאל אותי פעם מדוע ארבעים לקוחות קיבלו דואל חידוש פעמיים. התשובה לקחה שעה למצוא והייתה ארצית לחלוטין: רשימת הקמפיין הורכבה על ידי הדבקת ייצוא אחד תחת אחר, וארבעים כתובות היו קיימות בשתיהן. אף אחד לא בדק, כי בדיקה פירושה או עיניים של אלפיים שורות או כתיבת א VLOOKUP החצי הזה של הצוות עשה ' t trust. אז אף אחד לא בדק, ולאותם ארבעים אנשים נאמר פעמיים שהכרטיס שלהם עומד להיות מחויב.
זו הצורה של הבעיה הזו. ליישב שתי רשימות הוא אחד הדברים הנפוצים ביותר שמישהו עושה עם נתונים, וזה ' משעמם מספיק כדי שאנשים מדלגים על זה או עושים את זה רע. האינסטינקט הוא בדרך כלל להגיע לכלי הבדל, להדביק את שתי הרשימות ולפזול לפלט הצבעוני - שנכשל מיד, כי הבדל עונה על שאלה שעשית ' לא לשאול. או שאתה הולך לגיליון אלקטרוני ומתחיל להרכיב MATCH/COUNTIF נוסחאות, שעובדות אך אורכות עשר דקות ומייצרות חפץ you'לעולם לא תעשה שימוש חוזר.
הפעולה שאתה בעצם רוצה יש שם וזה & #39;s ישן יותר מכל הכלים: להגדיר אריתמטיקה. Intersection, הבדל, איחוד.I לבנות [Toolz.dev] (/ ולשים מבוסס דפדפן כלי השוואת רשימות שם, אבל המדריך הזה עוסק במושגים שמתחתיו - למה צריך להתעלם מהסדר, איזה תיק מתקפל נשבר בשקט, ואיך לבחור בין זה לבין הבדל.
TL;DR: כדי להשוות בין שתי רשימות, התייחסו לכל אחת כאל קבוצה לא מסודרת וחשבו את הצומת (פריטים בשתיהן), את שני ההבדלים (פריטים רק ב-A, פריטים רק ב-B), ואת הכפילויות בתוך כל רשימה. התעלם לחלוטין מהסדר - הבדל שורה הוא הכלי הלא נכון מכיוון שהוא ' s מיקום, כך שסדר מחדש של רשימה גורם כמעט לכל שורה להיראות שונה. קיפול מקרה עבור מזהים כמו מיילים אך שמור את הטקסט המקורי בפלט, קצץ רווח לבן לפני השוואה, ועשה זאת בדפדפן מכיוון שהרשימות שאנשים מתפייסים הן בדרך כלל נתוני לקוחות.
על אילו שאלות בעצם עונה השוואת שתי רשימות?
ברגע שאתה רואה את הפעולות בשם, הצורות הופכות ברורות. נתון רשימה א' ורשימה ב':
- צומת- מה's בשניהם? אילו מנויים הם גם לקוחות משלמים. איזה מהחודש שעבר 's מקט עדיין בקטלוג החודש 's.
- A מינוס B- what's רק ב-A? אילו משתמשים ב-CRM מעולם לא נכנסו לחיוב. אילו קבצים קיימים באופן מקומי אך לא בשרת.
- B מינוס A- מה's רק ב-B? אותה שאלה בכיוון השני, והיא's א שונה שְׁאֵלָה. חסרים מחיוב וחסרים מ-CRM הם שני באגים נפרדים עם שתי סיבות ברורות.
- הבדל סימטרי- what's ברשימה אחת בדיוק? האיחוד של שני ההבדלים: כל מה שלא הצליח להתאים, ללא קשר לכיוון. זהו ה-"what's לא מסונכרן?" שְׁאֵלָה.
- איחוד- הכל מכל אחת מהרשימות, לא משוכפל. המיזוג, נעשה כהלכה.
- כפילויות בתוך רשימה- what's חוזר על עצמו בתוך A לבד? זה הוא 't השוואה בכלל, אבל זה 's תמיד השאלה שאתה מתברר שהיית צריך, כי זה 's מה גורם לשליחות כפולות וחיוב כפול.
כדאי להפריד את האחרון הזה. התאמה בין רשימות ושכפול בתוך הרשימה הם בלתי תלויים: כתובת יכולה להופיע פעמיים ב-A ו מופיעים גם ב. כלים המדווחים רק על תוצאות צולבות מפספסים את הכישלון שעולה כסף.
הכל כאן ממפה ישירות לפעולות שאתה כבר מכיר מ-SQL - INTERSECT, EXCEPT, UNION- ועל נוסחאות גיליון אלקטרוני הערך של כלי ייעודי הוא 't שהוא עושה משהו שאתה יכול't; it's שכל שש התשובות מופיעות מהדבקה אחת, במקום שש נוסחאות שונות.
מדוע כלי הבדל הוא הבחירה השגויה להשוואת רשימות?
זו הטעות שאני רואה הכי הרבה, וכדאי לדייק בה 's, כי "השווה שתי רשימות" ו-"הבדל שני קבצים" נשמע כמו מילים נרדפות.
הבדל הוא מיקום. אלגוריתמי הבדל מחשבים את סקריפט העריכה המינימלי - הרצף הקצר ביותר של הוספות ומחיקות שהופך רצף אחד לשני. That' הוא המודל הנכון לקוד מקור ופרוזה, כאשר שורה 40 אחרי שורה 39 היא משמעותי. הזז פונקציה ו-diff מדווח בצורה נכונה שהזזת פונקציה.
לרשימה אין סדר משמעותי. לשורה 300 בייצוא ה-CRM שלך אין קשר כלשהו לשורה 300 בייצוא החיוב שלך. הם' הם שתי שקיות של פריטים שבמקרה נכתבו בכל רצף שמסד הנתונים החזיר.
הזינו נתונים לא מסודרים לאלגוריתם מיקום ותקבלו רעש. קח שתי רשימות עם תוכן זהה, מיין אחת מהן והבדל אותן:
List A List B
alice bob
bob alice
carol carol
הבדל מדווח על כך alice הוסר ונוסף מחדש, או ש bob הוזז - קצת נטישה פרופורציונלית לכמה שונים השניים ממוינים התשובה הנכונה היא שום דבר לא השתנה. כל פריט נמצא בשתי הרשימות. הסטים שווים. הבדל יכול't לומר את זה כי זה 't שואל על חברות.
טבלת ההשוואה, שכן הכלים באמת חופפים במוחם של אנשים שמחפשים את שניהם:
| רשימה השווה | הבדל טקסט | |
|---|---|---|
| דגם | סט פריטים לא מסודר | רצף מסודר של שורות |
| ענייני סדר? | לא - סדר מחדש בחופשיות, התוצאות זהות | כן - סדר מחדש של מופעים כשינויים |
| תשובות | חברות: בשניהם, רק א', רק ב', משוכפל | עריכות: מה להכניס/למחוק כדי להפוך את A ל-B |
| שכפול פריטים | דווח במפורש כקבוצה | רק עוד שורות |
| טוב ל | התאמה בין יצוא, רשימות דואל, תעודות זהות, מקט, מלאי | קוד מקור, פרוזה, קבצי תצורה, כל דבר שבו המיקום הוא משמעות |
| רע בשביל | השוואת שתי גרסאות של מסמך | כל רשימה שבה סדר המיון הוא שרירותי |
הכלל: אם אתה' תהיה מרוצה באותה מידה מהרשימה ממוינת אחרת, אתה רוצה השוואה מוגדרת. אם סדר מחדש של השורות יהיה שינוי אמיתי ששווה לדווח עליו, אתה רוצה את בודק הבדל טקסט. עבור נתונים מובנים עם קינון ולא קווים שטוחים, אף אחד מהם לא חל - זה' מה ה JSON Diff הוא עבור, מכיוון שהוא משווה לפי נתיב מפתח ולא לפי קו או לפי חברות.
כיצד צריכה לעבוד רגישות למקרה?
זוהי האפשרות שאנשים עוזבים כברירת מחדל ואז טועים בשקט, אז זה 's שווה לחשוב על פעם אחת.
התאמה לא תלוית רישיות היא ברירת המחדל הנכונה עבור הנתונים שרוב האנשים משווים. כתובות דואל, שמות משתמש, שמות דומיין, קודי מוצר, קודי מדינה - אלה בדרך כלל לא רגישים לרישיות בפועל, וכן [email protected] ו [email protected] האם אותו אדם בכל מערכת שחשובה.
There's אזהרה פדנטית כאן ש-'s שווה לדעת כי זה 's מדי פעם נושא עומס: לכל RFC 5321, חלק הדומיין של כתובת דואר אלקטרוני אינו רגיש לרישיות, אבל מקומי חלק - הכל לפני ה @- הוא רגיש רישיות באופן רשמי ונשאר לשרת הדואר המקבל לפרש. כך [email protected] ו [email protected] יכול באופן עקרוני להיות תיבות דואר שונות. בפועל בעצם כל ספק גדול מתייחס אליהם כאל זהים, ואם אתה ' מבטלים את שכפול רשימת התפוצה, עליך לקפל את המקרה לחלוטין. אבל אם אתה ' מאתר באגים מדוע כתובת ספציפית אחת קופצת, זה ' זה סוג הפרטים שמתברר שהם חשובים.
מקרה-רגיש ההתאמה נכונה לכל דבר שבו המקרה נושא מידע: נתיבי קבצים של לינוקס, מחרוזות base64, hashes, אסימוני JWT, מפתחות API, Git SHAs, רוב מזהי התכנות. קיפול מקרה ברשימת גיבוב סיסמאות ימזג ערכים נפרדים וייתן לך תשובה שגויה בביטחון.
פרט היישום שחשוב יותר מהאופציה עצמה: מקפלים את המארז להתאמה, אך מציגים את הטקסט המקורי. אם תדביק [email protected] והכלי אומר לך את זה ' בשתי הרשימות, זה צריך להחזיר [email protected]- לא [email protected]. הורדת הפלט משחיתה בשקט את הנתונים שלך בדרך, ומכיוון שהשלב הבא הרגיל הוא הדבקת התוצאה במקום אחר, השחיתות הזו עוברת. הכלי שומר על הצורה הנראית הראשונה של כל פריט ומתאים על מקש מקופל מאחורי הקלעים, אז מה שיוצא זה מה שאתה מכניס.
Whitespace ראוי לאותו יחס ומקבל פחות מחשבה העתק עמודה מתוך גיליון אלקטרוני, או פצל שורה כמו a, b, c על פסיקים, ואתה מקבל פריטים הנושאים רווחים מובילים. [email protected] ו [email protected] האם מחרוזות שונות וכתובות זהות. Trimming מופעל כברירת מחדל מסיבה זו, וזה 's האפשרות you'd הודעה חסרה תוך כשלושים שניות מהשימוש האמיתי.
באיזה מפריד עלי להשתמש?
ברירת המחדל היא פריט אחד בכל שורה, וזה מה שאתה מקבל בהדבקת עמודה של גיליון אלקטרוני - הלוח מעביר ערכים מופרדים בשורה חדשה, כך שעמודה של מיילים מ-Excel, Google Sheets או ייצוא CSV נכנסת ללא עיצוב מחדש.
המפרידים האחרים מכסים נתונים שמגיעים כבר בשורה. פסיק לשורת CSV בודדת או מערך מועתק. נקודה-פסיק עבור מוסכמות Outlook ו-wolder-Windows עבור רשימות כתובות. מקום לפלט מעטפת - ls, git diff --name-only עבר בצנרת tr, כל דבר מופרד ברווח. כרטיסייה לשורה מודבקת מגיליון אלקטרוני אופקית ולא אנכית.
דבר אחד שיש לשים לב אליו: פיצול בפסיקים הוא לא ניתוח CSV. שדה CSV אמיתי יכול להכיל פסיק בתוך מרכאות, ופיצול נאיבי ייקרע "Smith, Jane" לתוך שני פריטים.If you're משיכת עמודה אחת מתוך קובץ CSV אמיתי עם שדות מצוטטים, הפעל אותו דרך ה מציג CSV ראשית - הוא מיישם את כללי הציטוט בפועל של RFC 4180 - ואז העתק את העמודה הרצויה. לרשימה שטוחה של מיילים או מזהים ללא פסיקים משובצים, הפיצול בסדר וזה 't לעלות.
ערכים ריקים נשמטים כברירת מחדל, מכיוון שהם ' הם כמעט תמיד חפצים: שורה חדשה נגררת בסוף הדבק, שורה ריקה בגיליון אלקטרוני, פסיק כפול. מחרוזת ריקה היא 't פריט בכל רשימה שבאמת אכפת לך ממנה. האפשרות קיימת אם אתה ' מחפשים במיוחד שורות ריקות בייצוא, וזה דבר אמיתי אם לא שכיח לרצות.
איך ההשוואה מתרחבת?
הגישה הנאיבית להשוואת שתי רשימות היא לולאה מקוננת: עבור כל פריט ב-A, סרוק את כל B. That's O (n×m), ו-it' בסדר עבור מאה פריטים ולא שמיש עבור חמישים אלף, כאשר אתה 'עושים השוואות של 2.5 מיליארד מחרוזות.
הגישה הנכונה מאנדקס כל רשימה למפת גיבוב המקושרת על ידי מפתח ההשוואה - הצורה המקופלת, הגזומה של הפריט - כשהערך הוא המקור שנראה לראשונה בניית כל אינדקס היא מעבר ליניארי אחד ואז כל שאלה הופכת לחיפוש בזמן קבוע לכל פריט: האם המפתח הזה נמצא ב-B's map? כל ההשוואה היא O (n+m), מה שאומר שעשרים אלף פריטים בכל צד הם ארבעים אלף פעולות גיבוב ומסתיימים מהר יותר ממה שהדפדפן יכול לצבוע מחדש.
אותו אינדקס נותן כפילויות בחינם ספירת מופעים לכל מפתח בזמן בנייתו; כל מפתח עם ספירה מעל אחד משוכפל בתוך הרשימה הזו. אין מעבר שני, אין מבנה נוסף.
בפועל התקרה היא 't ההשוואה - it's הדפדפן המציג קבוצת תוצאות עם חמישים אלף שורות לאזור טקסט. החשבון מסתיים באלפיות שניות ללא קשר. אם אתה ' אתה מיישב באופן שגרתי רשימות כל כך גדולות, אתה כנראה רוצה את זה בסקריפט ולא בכרטיסייה, והאלגוריתם שלמעלה הוא כעשר שורות בכל שפה.
מיון שווה הערה התוצאות ממוינות באופן טבעי כברירת מחדל, כלומר מודעות מספרית: item2 לפני item10, לא אחריו. מיון לקסיקוגרפי רגיל מעמיד item10 ראשית בגלל 1 < 2 תו אחר תו, שנכון לפי האות של השוואת מחרוזות ושגוי לפי כל ציפייה אנושית בעת סריקת מזהים או שמות מנוסחים כבה את המיון ותקבל סדר הכנסה - פריטים ברצף שהם הופיעו לראשונה ב-A, ואז ב-B - וזה מדי פעם מה שאתה רוצה כשהסדר המקורי מקודד משהו כמו עדכניות.
איך זה נראה בפועל?
ארבעה תרחישים שבהם I' למעשה השתמשתי בזה, כל מיפוי לקבוצת תוצאות אחרת.
ניקוי רשימת תפוצה לפני שליחה. הדבק את הרשימה החדשה ואת הרשימה שנשלחה קודם לכן. רק בא' האם למי יש 'לא יצרו קשר - that's רשימת השליחה שלך. בשניהם האם who'd לקבל כפיל. כפילויות ב-A האם ארבעים האנשים מהסיפור בראש עמוד זה. הבדיקה הזו אורכת חמש עשרה שניות והיא ' היא זו שהייתה חוסכת למהנדס התמיכה שעה.
התאמה בין שתי מערכות. ייצוא מיילים של משתמשים מה-CRM ל-A ומחיוב ל-B. רק בא' נרשם-אך-לעולם-לא-מוכר; רק ב-ב מחויב-אך-חסר-מ-CRM. אלו שני באגים שונים. הראשון עשוי להיות וו אינטרנט שבור, השני עשוי להיות חשבונית ידנית שמישהו העלה מחוץ לזרימה. " הרשימות הללו שונות" התשובה תטשטש את זה לחלוטין, וזו בדיוק הסיבה ששני הכיוונים מדווחים בנפרד.
סחף מלאי וקטלוג. בחודש שעבר 's ייצוא מקט מול החודש 's. רק בא' מופסק, רק ב-ב הוא חדש, בשניהם מועבר מיון עניינים כאן - היצוא יוצא ממערכות שונות בסדרים שונים, והבדל ידווח על כל הקובץ כפי שהשתנה.
בדיקות שפיות פריסה. קבצים על בימוי לעומת קבצים על הפקה, משניים ls יציאות מודבקות עם מפריד הרווחים. רק בא' זה מה ש-' עדיין לא נשלח.
הדפוס על פני כל הארבעה: התשובה השימושית היא כמעט אף פעם "הרשימות שונות." It's אשר פריטים, ב אשר כיוון - וזה בדיוק מה שפעולות סט נותנות לך ומה ציון דמיון או סיכום הבדל 't.
האם הרשימות שלי מועלות בכל מקום?
לא, ותחשוב לרגע על מה שאתה 'd להדביק לתוך כלי כזה.
It's a subscriber export.A רשימה של הודעות דואל של לקוחות. Employee IDs. License numbers. Account numbers. the lists people college are, by their nature, close to the most sensitive data an organization holds - you don't conciliate lists of nothing, you conciliate lists of אנשים. ו-" תן לי פשוט להדביק את אלפיים הודעות הדואל של לקוחות אלה באתר אקראי כדי לבדוק אם יש חפיפה " הוא משפט שאמור לעצור אותך קר, כי בהרבה תחומי שיפוט ש-' הוא מערכת יחסים עם מעבד שיצרת זה עתה ללא חוזה.
There's אין סיבה לחישוב הזה לגעת ברשת. It's hash maps over strings - כמה מאות שורות של TypeScript ללא תלות. הכלי ב-Toolz.dev פועל כולו בכרטיסייה שלך; הרשימות הן מחרוזות JavaScript בדפדפן שלך's זיכרון והן אף פעם לא עוזבות אותו. שום דבר לא מועלה, נרשם או מאוחסן. אמת זאת כפי שאתה 'd אמת כל טענה כזו: פתח את לשונית הרשת ולחץ על השווה, או כבה את ה-wifi שלך וראה אותו ממשיך לעבוד. I' כתבתי עוד על מדוע הארכיטקטורה הזו חשובה בדיוק לסוג הנתונים הזה מדוע כלים מבוססי דפדפן מנצחים את הכלים בצד השרת.
שָׁוא
כיצד אוכל להשוות שתי רשימות כדי למצוא את מה שיש להן במשותף?
הדבק רשימה אחת ברשימה A, השנייה ברשימה B, ולחץ על השווה. The "In Both" group is the intersection - כל פריט הקיים בשתי הרשימות. you can copy that group on its own, download it as a text file, or export every group at one with Copy Report. Order does't matter, so the lists don't need to be sorted the same way.
איך אני מוצא פריטים שנמצאים ברשימה אחת אבל לא ברשימה השנייה?
ה-"Only ב-A" ו-"Only ב-B" קבוצות עונות על כך, והן' נפרדות בכוונה. רק ב-A מחזיק פריטים חסרים ברשימה B; רק ב-B מכיל פריטים חסרים ברשימה A. בדרך כלל מדובר בבעיות שונות עם סיבות שונות - חסר מחיוב וחסר מ-CRM aren' באותו באג - אז קריסתם לתשובה אחת מאבדת את המידע שאתה צריך. "Unique" הקבוצה משלבת את שניהם אם אתה רוצה את ההבדל הסימטרי.
האם זה יכול למצוא כפילויות בתוך רשימה אחת?
כן. משכפל ברשימה A ומשכפל ברשימה B כל פריט נפרד המופיע יותר מפעם אחת ברשימה זו. זה בלתי תלוי בהתאמה בין רשימות, כך שניתן לשכפל פריט גם ב-A וגם להציג ב-B. It' בדרך כלל הבדיקה החשובה ביותר בפועל, שכן כפילויות בתוך הרשימה הן שגורמות לכפילות מיילים וחיוב כפול.
האם היוון משפיע על ההשוואה?
רק אם אתה רוצה את זה. התאמה תלוית רישיות כבויה כברירת מחדל, אז [email protected] ו [email protected] מטופלים כפריט אחד - והפלט שומר על כל טופס שהדבקת במקום להקטין את הנתונים שלך. הפעל אותו עבור ערכים שבהם המקרה נושא משמעות: נתיבי לינוקס, מחרוזות base64, hashes, מפתחות API, Git SHAs.
מה 's ההבדל בין זה לבין כלי הבדל טקסט?
הבדל הוא מיקום: הוא משווה שורה 1 לשורה 1 ומחשב את העריכות הדרושות כדי להפוך רצף אחד לשני, כך שסדר מחדש של רשימה גורם כמעט לכל שורה להיראות שונה. כלי זה מתעלם לחלוטין מהסדר ושואל רק אם קיים פריט בכל צד. השתמש ב-diff עבור קוד ופרוזה כאשר המיקום הוא משמעות; השתמש ברשימה השווה עבור התאמה בין יצוא כאשר סדר המיון הוא שרירותי.
האם אני יכול להשוות רשימות מופרדות בפסיקים במקום שורות חדשות?
כן - החלף את המפריד לפסיק, נקודה-פסיק, רווח או כרטיסייה. רווח לבן סביב כל פריט נחתך כברירת מחדל, אז a, b, c מתפצל לשלושה פריטים נקיים אזהרה אחת: פיצול בפסיקים is' ניתוח CSV אמיתי, אז אם הנתונים שלך ציטטו שדות המכילים פסיקים, חלץ תחילה את העמודה עם כלי CSV מתאים.
בכמה פריטים זה יכול להתמודד?
ההשוואה מאנדקסים כל רשימה למפת גיבוב ופועלת בזמן ליניארי ולא באמצעות לולאות מקוננות, כך שעשרות אלפי פריטים בכל צד משלימים באלפיות שניות התקרה המעשית היא הדפדפן שלך המציג קבוצת תוצאות גדולה מאוד לתוך הדף, לא ההשוואה עצמה.
האם הרשימות שלי מועלות בכל מקום?
מס 'כל הניתוח וההשוואה קורה כמו JavaScript בדפדפן שלך - שום דבר לא מועבר, נרשם, או מאוחסן זה משנה כאן יותר מאשר עבור רוב הכלים, כי הרשימות אנשים מתפייסים הם בדרך כלל הודעות דואל של לקוחות, מזהה עובדים, או מפתחות רישיון צפה בכרטיסיית הרשת שלך בזמן השוואה, או ללכת לא מקוון וזה ממשיך לעבוד.
כלים קשורים: בודק הבדל טקסט כאשר הסדר והעמדה חשובים, JSON Diff לנתונים מובנים, מציג CSV לחילוץ עמודה מ-CSV אמיתי, ו מונה מילים לספירות מהירות קריאה נוספת: מדוע כלים מבוססי דפדפן מנצחים את הכלים בצד השרת ו מפתח האינטרנט's ערכת כלים.



