ייעול של פונקציות החיפוש
-
@HSF
כאן העלתי דוגמא לקוד באקסס, שנ"ל קצר יותר.כשבכל שדה בודק איזה סינון להחיל עליו.
כשבסוף מצרף את כל הסינוניםאני לא מבין VB וניסיתי להמיר אותו כאן אבל זה כתב שיש לו שגיאה ושהוא לא יכול להמיר את הקובץ
לא הבנתי אותך.. אתה בעצם מחפש לפי כל פרמטר בנפרד, ואח"כ מקבץ את כל התוצאות, ואז שוב מבצע סינון?? שהרי זה לא עוזר לי שיהיו לי את כל התוצאות שהרי אם הוא מזין נתונים בכמה מקומות אז הוא רוצה לסנן גם ע"פ הפרמטר הזה וגם הזה והזה.. אז בעצם מראש צריך להריץ שאילתא אחת שתסנן ע"פ כל הפרמטרים?? נמצא שצריך לכתוב שאילתא לכל שילוב אפשרי ולפי מה שהמשתמש מזין לדעת באיזה שאילתא לבחור..אני מכין מראש את נוסחת הסינון לכל פרמטר בנפרד, ומשתמש בפונקציית IF שאם לא בחר סינו יוסיף סינון "" ובמידה ובחר סינון אחר (כגון: שווה ל.. /החל מ /עד/בין/גדול/קטן, כל דבר לפי ענינו) מוסיף את הנוסחה למשתנה פנימי בהתאם לפרמטר שלו.
ולבסוף אני מאחד את כל הסינונים.ולדוגמא הסינון של סכום מאוחסן במשתנה X
הסינון של תאריך מאוחסן במשתנה XX
בסוף אני עושה איחוד של X & XX ומוסיף אותו לשורת הסינון בשאילתה
במידה ואין שום סינון הרי נוסף רק "" כאמור.פורסם במקור בפורום CODE613 ב09/08/2015 18:34 (+03:00)
-
קודם כל אתה מסנן רשימות ולא דטהבייס ויש הבדל גדול
לסינון מול דטהבייס יש כלים שיודעים לבנות לך שאילתה מכל הבלגאן הזהANYWAY מה שכתבת הוא קוד ספגטי קלאסי - דע לעתיד שאם קוד מגיע לכזו רמת סיבוכיות אז משהו בגישה שלך לא נכון (אקסס - יוצא מן הכלל)
לסינון רשימות אפשר לעשות סינון חוזר של אותה רשימה משהו כזה:
static void Main(string[] args) { List<Donor> dnrSource = new List<Donor>(); dnrSource.Add(new Donor { FirstName = "John", LastName = "Doe", Address = "31 Peachtree st."}); dnrSource.Add(new Donor { FirstName = "Jane", LastName = "Doe", Address = "31 Peachtree st." }); dnrSource.Add(new Donor { FirstName = "Jane", LastName = "Doe" }); List<Donor> dnrFiltered = new List<Donor>(dnrSource.ToArray()); if (!string.IsNullOrEmpty(FirstNameSearch.Text)) { dnrFiltered = new List<Donor>(SearchString(dnrFiltered, "FirstName", FirstNameSearch.Text)); } if (!string.IsNullOrEmpty(LastNamesearch.Text)) { dnrFiltered = new List<Donor>(SearchString(dnrFiltered, "LastName", LastNamesearch.Text)); } if (!string.IsNullOrEmpty(Addresssearch.Text)) { dnrFiltered = new List<Donor>(SearchString(dnrFiltered, "Address", Addresssearch.Text)); } }
פורסם במקור בפורום CODE613 ב09/08/2015 20:17 (+03:00)
-
ANYWAY מה שכתבת הוא קוד ספגטי קלאסי - דע לעתיד שאם קוד מגיע לכזו רמת סיבוכיות אז משהו בגישה שלך לא נכון (אקסס - יוצא מן הכלל)
בדיוק לכן שאלתי, כי זה היה נראה לי מוזר.. ארוך ומיותר..
יישבתי הרבה כדי ללמוד ולהבין את הקוד שכתבת..
לבסוף נפל לי האסימון למה התכוונתם (אתה וHSF)(בסוף הוא נופל :lol: :lol: )
בעצם אתם מריצים חיפוש של פרמטר אחד (לדוג' שם) ואז על הרשימה שהתקבלה אתם מריצים את החיפוש השני (לדוג' של הכתובת) ועל הרשימה המצומצמת שמתקבלת אתם מריצים את השלישי וכו'.
כך גם אתה פותר את הבעיה שהסתבכתי איתה לכתוב את כל הוריאציות של הצירופים האפשריים, אלא אתה עושה IF כמספר התיבות טקסט, ואם המשתמש הזין טקסט אתה מריץ חיפוש על הרשימה שהתקבלה מהחיפוש הקודם.
כ"כ פשוט!! איך לא חשבתי על זה :shock: ישבתי הרבה זמן לכתוב את הקוד הזה (שהוא הרבה יותר ארוך ממה שהבאתי כאן.. מה שעשיתי כאן זה היה רק בשביל חיפוש של פרמטר אחד..)
תודה רבה רבה שהארתם את עיני!!!פורסם במקור בפורום CODE613 ב09/08/2015 22:43 (+03:00)
-
פונקציה כללית לחיפוש יכולה להיראות כך:
public static IEnumerable<T> SearchString<T>(IEnumerable<T> lst, string sProperty, string sVal)
{MemberInfo mi = ((MemberInfo)typeof(T).GetField(sProperty) ?? (MemberInfo)typeof(T).GetProperty(sProperty)); if (mi == null) throw new ArgumentException("Field/Property does not exists", "sProperty"); if (mi.MemberType == MemberTypes.Property) { return lst.Where(d => (((PropertyInfo)mi).GetValue(d) ?? "").ToString().Contains(sVal)); } else { return lst.Where(d => (((FieldInfo)mi).GetValue(d) ?? "").ToString().Contains(sVal)); } }
הפונקציה הזו טובה כשהערך הוא string
ניסיתי לכתוב מתודה גנרית דומה שיכולה לחפש כשהמאפיין הוא מסוג double או int (כיון שעם הפונקציה הזאת הוא זרק לי חריג שהערך אינו מתאים).
לא הצלחתי..
ניסיתי לכתוב בתוך הcontains (double.parse) ואז את הערך.. אבל זה לא הצליח כיון שלפני זה יש Tostring ניסיתי למחוק את זה אבל אז הוא לא נותן לי את הcontains.. בקיצור - הסתבכתי
אשמח לשמוע מה לעשות...
וגם מדוע בכלל אתה צריך את הtostring הזה?
תודה רבה!!פורסם במקור בפורום CODE613 ב10/08/2015 23:20 (+03:00)
-
למה צריך את ה ToString? כי GetValue מחזיר object כי הוא לא יודע מה סוג ה property ואי אפשר להשוות object ל string בלי ToString
פונקציה כללית:public static IEnumerable<T> Search<T>(IEnumerable<T> lst, string sProperty, dynamic Val, bool contains = false) { MemberInfo mi = ((MemberInfo)typeof(T).GetField(sProperty) ?? (MemberInfo)typeof(T).GetProperty(sProperty)); if (mi == null) throw new ArgumentException("Field/Property does not exists", "sProperty"); if (mi.MemberType == MemberTypes.Property) { PropertyInfo pi = (PropertyInfo)mi; return lst.Where(d => Match((pi.GetValue(d) ?? "").ToString(), Val.ToString(), contains)); } else { FieldInfo fi = (FieldInfo)mi; return lst.Where(d => Match((fi.GetValue(d) ?? "").ToString(), Val.ToString(), contains)); } } public static bool Match(string sLeft,string sRight, bool contains) { return (sLeft == sRight || (contains && sLeft.Contains(sRight))); }
פורסם במקור בפורום CODE613 ב11/08/2015 13:47 (+03:00)
-
return lst.Where(d => Match((pi.GetValue(d) ?? "").ToString(), Val.ToString(), contains public static bool Match(string sLeft,string sRight, bool contains) { return (sLeft == sRight || (contains && sLeft.Contains(sRight))); }
אשמח אם תוכל להסביר לי מה בעצם אתה עושה ב2 השורות הללו?
תודה רבה רבה!! כנראה שיש לי עוד הרבה פערים להשלים :lol: :lol:פורסם במקור בפורום CODE613 ב11/08/2015 16:08 (+03:00)
-
תודה רבה soft על כל העזרה עם הפונקציות!!דרך זה למדתי על עולם שלם שלא כ"כ הכרתי..
(על כל ספריית הReflection "שיקוף" בלע"ז :lol: )
לאט לאט אני מגלה עולם..
ובכל אופן זו הייתה טעות שלי.. הפונקציה הראשונה עובדת טוב גם על מאפיינים של INT וDOUBLE, הייתה לי שגיאה אחרת שבגללה הוא זרק לי את החריג שהערך אינו מתאים
בכל אופן תיקנתי אותה.. ועכשיו הכל רץ חלק!! (גם אם אני משתמש בפונקציה הראשונה וגם אם בשניה..)פורסם במקור בפורום CODE613 ב11/08/2015 20:04 (+03:00)