דחוף!!! אלגוריתם להשוואת מחרוזות באמצעות רצפים שווים
-
שלום לכולם
בזמנו דיברתי עם דוד, יש הרבה אלגוריתמים מוכנים להשוואת מחרוזות, ודי חפרתי בנושא.
כרגע יש לי פרוייקט לחוץ מאוד, להשוואת וטיוב נתוני כתובות, צריך להשוות בין מאגרי אקסל שונים ומשונים ולאחד אותם, וכרגיל אין מפתח ראשי, אין תעודות זהות ואין כלום. מה שנתנו לי זה שמות, ישובים, וכתובות.
בקטע של כתובות זה הכי מרגיז, כי אין שום עקביות, הפקידה הקלידה פעם ככה ופעם ככה.
מצאתי קוד קטן וחמוד שעשיתי לפני הרבה שנים בVBA, הוא נותן תוצאות נחמדות, אבל למשל בהשוואה בין "רבי אליעזר 3" לבין "ר' אליעזר 3" הוא נותן את התוצאה 6, כאשר זה בעצם 7 בלי הרווחים, ו 9 עם הרווחים.
אני בעצם צריך אלגוריתם, שינסה "להניח" את המחרוזות זה ע"ג זה, בצורה הכי מיטבית, כלומר שבשורה למעלה יהיו כמה שיותר אותיות ששוות בדיוק לשורה למטה. הוא יזיז את המחרוזת העליונה שמאלה וימינה וירשום כמה תוצאות של "שיוויון" בין השורה העליונה לתחתונה יש לו בכל צעד, ואז יתן את התוצאה הגבוהה ביותר.
במקרה שלנו למשל כאשר הוא יציב את המחרוזות ככה:
-|ר|'| |א|ל|י|ע|ז|ר| |3|
ר|ב|י| |א|ל|י|ע|ז|ר| |3|
הוא יגיע מיידית ל 9.
אני מודע לכך שהאלגוריתם הזה לא מספיק טוב, כי הוא לא מכסה את הנושא של ווים ויודים שמתווספים באמצע מילה, אבל בשביל להשלים את הסוגיה, הייתי רוצה אלגוריתם כזה.
כמובן שאפשר לכתוב את הקוד, וזה אתגר נחמד מאוד, אבל אין לי הזמן לכך בפרוייקט הקטן הנוכחי שצריך להסתיים תוך שעתיים, אם מישהו יודע על קוד מוכן אשמח לקבל.
זה הקוד שכתבתי בזמנו למי שמעוניין (אמרתי שזה לפני הרבה שנים, יש שם הרבה חוסר מקצועיות בלשון המעטה אז לצחוק בשקט לא בקול :oops:Function מספר_מופעים_בתוך_מחרוזת(ByVal מחרוזת As String, ByVal מופע As String) As Long Dim מספר As Long, כמות_תווים As Long כמות_תווים = Len(מופע) For i = 1 To Len(מחרוזת) If Mid(מחרוזת, i, כמות_תווים) = מופע Then מספר = מספר + 1: i = i + (כמות_תווים - 1) Next מספר_מופעים_בתוך_מחרוזת = מספר End Function Function החזר_מיקום_בתוך_מחרוזת(ByVal מחרוזת As String, ByVal מיקום As Integer, תו_הפרדה As String) As Variant 'תפקיד הפונקציה הוא להחזיר את הרצף הרלוונטי מתוך מיקום מסויים בתוך מחרוזת 'האפשרות לפי תו הפרדה מאפשרת להחזיר גם שלש תווים או יותר ובלבד שהם במיקום מסויים בין שני תווי הפרדה 'אם הוא מושמט או אפס תווי ההפרדה יהוו חלק ממשי מהמחרוזת Dim מיקום_תו_הפרדה_נוכחי, מיקום_תו_הפרדה_משמאל, אורך_מחרוזת, מחרוזת_בעיבוד, כמות_תווי_הפרדה 'מחפש את המיקום של התו_הפרדה המבוקש שהוא התו_הפרדה שאחרי הספרה שאותה אנו מבקשים מבוצע על ידי לולאה הואיל ופונקציית אין סטר מחזירה רק מהמקום הראשון מחרוזת_בעיבוד = מחרוזת 'לולאה זו מחפשת את מיקום התו_הפרדה משמאל מחרוזת_בעיבוד = מחרוזת If מיקום = 1 Then GoTo קצץ_תווי_הפרדה_משמאל For i = 1 To מיקום מיקום_תו_הפרדה_נוכחי = InStr(1, מחרוזת_בעיבוד, תו_הפרדה) If מיקום_תו_הפרדה_נוכחי = 0 Then מיקום_תו_הפרדה_נוכחי = Len(מחרוזת_בעיבוד) אורך_מחרוזת = Len(מחרוזת_בעיבוד) מחרוזת_בעיבוד = Right(מחרוזת_בעיבוד, אורך_מחרוזת - מיקום_תו_הפרדה_נוכחי) מיקום_תו_הפרדה_משמאל = Nz(מיקום_תו_הפרדה_משמאל, 0) + מיקום_תו_הפרדה_נוכחי Next 'כאשר מקום התו_הפרדה משמאל ידוע ניתן ערך למחרוזת שרק התווים השמאליים עד מיקום התו_הפרדה יופיעו If Len(מחרוזת) > מיקום_תו_הפרדה_משמאל Then מחרוזת_בעיבוד = Left(מחרוזת, מיקום_תו_הפרדה_משמאל - 1) Else מחרוזת_בעיבוד = מחרוזת 'כעת יש לנו לקצץ את המחרוזת מהצד השמאלי עד שנקבל ערך ללא תווי_הפרדה קצץ_תווי_הפרדה_משמאל: Do אורך_מחרוזת = Len(מחרוזת_בעיבוד) If מיקום = 1 Then מחרוזת_בעיבוד = Left(מחרוזת_בעיבוד, אורך_מחרוזת - 1) Else מחרוזת_בעיבוד = Right(מחרוזת_בעיבוד, אורך_מחרוזת - 1) If Not מחרוזת_בעיבוד Like "*" & תו_הפרדה & "*" Then Exit Do Loop Until Len(מחרוזת_בעיבוד) <= 1 תוצאה_סופית: החזר_מיקום_בתוך_מחרוזת = מחרוזת_בעיבוד End Function Function מספר_התאמות_בין_מחרוזות(ByVal מחרוזת As String, מחרוזת2 As String) As Long Dim מספר As Long, ציון_אחרון As Long מספר = 0 ציון_אחרון = 0 For i = 1 To מספר_מופעים_בתוך_מחרוזת(מחרוזת, " ") + 1 If מחרוזת2 Like "*" & החזר_מיקום_בתוך_מחרוזת(מחרוזת, i, " ") & "*" Then מספר = מספר + 1 If ציון_אחרון = (i - 1) Then מספר = מספר + 1 ציון_אחרון = i End If Next For i = 1 To מספר_מופעים_בתוך_מחרוזת(מחרוזת2, " ") + 1 If מחרוזת Like "*" & החזר_מיקום_בתוך_מחרוזת(מחרוזת2, i, " ") & "*" Then מספר = מספר + 1 If ציון_אחרון = (i - 1) Then מספר = מספר + 1 ציון_אחרון = i End If Next מספר_התאמות_בין_מחרוזות = מספר End Function
תודה.
פורסם במקור בפורום CODE613 ב05/11/2014 10:42 (+02:00)
-
בל על זמנך, אתה מחפש בדיוק מה שמליונים חיפשו לפניך. נדמה לי שזה בדיוק מה שועשה אלגוריתם מרחק לוינשטיין.
הנה מימוש בשפות רבות כולל VBA.: http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance.פורסם במקור בפורום CODE613 ב05/11/2014 12:26 (+02:00)
-
מעניין אותי לחשוב בכיוון שונה.
יש לי DB שהיה נכון ללפני שנתיים, ששם יש את רשימת הרחובות המלאה בארץ כולל כל ההטיות של כל רחוב, והסמל שלהם.
אמנם, תצטרך לפצל את מס' הבית לעמודה שונה, אבל אחרי זה תוכל להשוות את כל הרחובות לפי הערים שלהם.
כמובן שגם הערים נמצאים כל אחד עם כל ההטיות שלו,לדוגמא: פ"ת,פתח תקווה פתח תקוה וכו'.
אם אתה מעוניין, שלח לי בפרטי.פיתרון נוסף,שיכול להיות לך טוב זה לבדוק את זה ברשות הדואר, כי הרי יש לך קוד שבודק ומשלים את הרחובות באונליין מבדיקת המיקוד :), ואז הנתונים שלך יהיו נכונים להיום.
פורסם במקור בפורום CODE613 ב05/11/2014 12:27 (+02:00)
-
טוב קודם כל מרחק לווינשטיין עזר מאוד והצליח לקדם את העבודה האנושית בעשרות אחוזים, אני עכשיו נזכר מלפני שנתיים שחפרנו הרבה בנושא ולפי מה שקראתי זה אחד האלגוריתמים המרכזיים.
לגבי ההצעה של קליק, לא מדובר בהטיות לגיטימיות, נראה לי שכל מסדי נתונים בעולם לא יכולים לכסות שגיאות של פקידות, מה שכן אתה יכול לפתח אלגוריתם שיתן לך הערכה באיזו כיתה המורה שלהם מתה :lol: :lol: :lol:
אני מצרף כאן רשימה (אמיתית התקבל ממרכז מענה אנושי) שבעים פנים לישיבת פוניבז' ותגיד לי אם יש לך מסד נתונים שמכיל באופן הזה את כל רחובות ישראל :lol: :
יוצאי פונביץ
יוצאי פונובי'ז
ישיבת כולל פוניבז
ישיבת פונוביז'
ישיבת פונובי'ץ
כולל יוצאי פוניבז
כולל פונביז
כולל פונביץ
כולל פונוביז
כולל פונוביז'
כולל פוניבז
כולל פוניבז'
פונוביז
פונוביז'
פונובי'ץ
פונוביש בני ברק
פוניבז
פוניב'ז
פוניבז'
פוניביץ
פנביז
פנוביז
פנוביץפורסם במקור בפורום CODE613 ב07/11/2014 11:43 (+02:00)
-
הקפצה:
יש מאוכזבים מלוינשטיין, והנה אחד שטוען שיש לו פתרון טוב יותר:
https://www.codeproject.com/Articles/1209269/Not-Levenshtein
אני חושב שלבעל המאמר יש טעות, כי לונשטיין לא בא לפתור את הדמיון האנושי בין מחרוזות אלא לזהות שגיאות הקלדה (אות חסירה ויתירה בשוגג) וממילא "מרחק עריכה".לעיון נוסף
https://stackoverflow.com/questions/5859561/getting-the-closest-string-matchפורסם במקור בפורום CODE613 ב13/11/2017 08:07 (+02:00)
-
ישנה אפשרות אחרת, לא יודע מי המציא אותה (אם בכלל).
ממירים כל מילה למילה מתומצת לפי כללים מסויימים.
כגון:
שבת=שבט
או:
פונוביז=פנבז
פוניבז=פנבז
וכמובן:
פונוביז'=פנבז
פוניבץ'=פנבץזה מאוד מקדם.
צריך לשאול את דעת ארכיטקסט.פורסם במקור בפורום CODE613 ב13/11/2017 12:23 (+02:00)
-
ישנה אפשרות אחרת, לא יודע מי המציא אותה (אם בכלל).
ממירים כל מילה למילה מתומצת לפי כללים מסויימים.
כגון:
שבת=שבט
או:
פונוביז=פנבז
פוניבז=פנבז
וכמובן:
פונוביז'=פנבז
פוניבץ'=פנבץזה מאוד מקדם.
צריך לשאול את דעת ארכיטקסט.בעברית זה רעיון אבל באנגלית זה כמעט לא ישים.
פורסם במקור בפורום CODE613 ב13/11/2017 15:26 (+02:00)
-