Linq שאלה - לא יעיל
-
יש לי את הקוד הבא שלוקח כל פריט השוואת מסמכים בוורד ועוטף אותו בהשוואות הסמוכות לו. אחרי זה מתבצע linq לגלות איזה סמיכות.
הבעיה היא, שכאשר זה קצת זה עובד בסדר. אבל כשזה הרבה יותר מידי הוא קורס. איך אני יכול להתשמש בכל זאת במנגנון הזה, גם על רשימות גדולות? כמו כן,ש אני רוצה לעמוד על הרשימה הזו, הוא חושב וחושב אבל נופל באמצע. אני מבין שזה קשור איfשהוא למה שדוד.ל.ט כתב כאן פעם שכל LINQ עובד עם yeild ואז באמת הרשימה לא קיימת בזכרון אלא רק מה שצריך. יש אפשרות לקבע את זה שלא יעבוד עם זה ויהיה ליסט רגיל (כמו שאני ניסתי לעשות, עם MSG וכן עם tolist() אבל ללא הצלחה)?var revisions = doc.Revisions.Cast<word.Revision>().ToList(); var revList = new List<revsInOrder>(); for (int i = 0; i < revisions.Count; i++) { word.Revision nxt; word.Revision pre; if (i != 0) { pre = revisions[i - 1]; } else { pre = null; } if (i != revisions.Count - 1) { nxt = revisions[i + 1]; } else { nxt = null; } revList.Add(new revsInOrder() { prev = pre, next = nxt, current = revisions[i] }); } var anotherlist = revList.Where(p => (p.next != null && (p.current.Range.End == p.next.Range.Start))).OrderByDescending(p => p.current.Index).ToList(); MessageBox.Show(anotherlist.Count.ToString()); foreach (var item in anotherlist) { item.current.Accept(); item.next.Accept(); }
פורסם במקור בפורום CODE613 ב20/08/2017 22:54 (+03:00)
-
וניסתי גם את זה אך גם הוא נתקע באמצע.
private void button9_Click(object sender, EventArgs e) { var things = GetAll(); things = things.Where(p => (p.next != null && (p.current.Range.End == p.next.Range.Start))).OrderByDescending(p => p.current.Index); } IEnumerable<revsInOrder> GetAll() { var app = (word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application"); var doc = app.ActiveDocument; var revisions = doc.Revisions.Cast<word.Revision>().ToList(); for (int i = 0; i < revisions.Count(); i++) { word.Revision nxt; word.Revision pre; if (i != 0) { pre = revisions[i - 1]; } else { pre = null; } if (i != revisions.Count - 1) { nxt = revisions[i + 1]; } else { nxt = null; } yield return new revsInOrder() { prev = pre, next = nxt, current = revisions[i] }; } } public class revsInOrder { public word.Revision prev { get; set; } public word.Revision current { get; set; } public word.Revision next { get; set; } }
פורסם במקור בפורום CODE613 ב20/08/2017 23:37 (+03:00)
-
אגב ייפתי את הקוד, לא מה שיציל אותך אבל לא התאפקתי:
var length = revisions.Count(); //first yield return new revsInOrder { prev = null, next = revisions[1], current = revisions[0] }; //loop over all exept first+last for (int i = 1; i < length - 1; i++) yield return new revsInOrder { prev = revisions[i - 1], next = revisions[i + 1], current = revisions[i] }; //last yield return new revsInOrder { prev = revisions[length - 2], next = null, current = revisions[length - 1] };
פורסם במקור בפורום CODE613 ב21/08/2017 11:02 (+03:00)
-
הוא גם לא עוצר בנקודות עצירה. הוא פשוט מראה את טופס האב שלו כאילו הכל בסדר.
כאני עומד על הליסט הוא כותב לי את זה
Error = Function evaluation disabled because a previous function evaluation timed out.
You must continue execution to reenable function evaluation.
אני מבין מזה שבגלל הכל yeild אז הוא מחכה שמשהו יקרה, והוא לא מפרגן לדיבאג לחשב את כל הליסט, הוא רוצה את הדבר האמיתי.
יפוי הקוד פותר את בעית הNULL בהתחלה ובסוף. חן.
אבל יש עם זה עוד משהו, גם אם איכשהוא הוא נותן את האופציה, והבעיה היא בגלל שזה יילד. כי נניח שאני רוצה לערוך שינויים בין לבין כלומר בים שאילתא לשאילתא. ולעבור על כולם ולקבל אותם או משהו כזה. בגלל זה יילד, הכל משתנה וזה מתחשב מחדש לאחר השינויים. ואוביקטים שהיו קיימים אז כבר לא קימים היום (בדוגמא לעיל נניח שקבלתי חלק מהשינויים במסמך). יש אפשרות "לקבע " את הליסט שלא יזוז ומה שהיה הוא שיהיה?פורסם במקור בפורום CODE613 ב21/08/2017 13:17 (+03:00)
-
אני נמנעתי אפי' מלחשוב כל עוד שלא כתבת מה השגיאה.
לא ביקשתי נקודת עצירה, אלא סה"כ הרצה מתוך הVS כך שכל נפילה בעולם מגובה בפרטים חשובים כמו שורת הנפילה, והודעה.כעת שהבאת שגיאה שמשמעותה היא בד"כ לולאה אין סופית וכיוצ"ב אני כמוך מתקשה להבין למה זה קורה.
אינני יודע מה אתה רוצה מהיילד, הוא דומה למעבר פרימיטיבי על אוסף. בשביל להקפיא את התוצאות גם אם יהיה שינוי בהמשך אתה יכול להריץ אותו מיידית עם ToList אבל זה לא עוזר לך לגבי כל איבר ואיבר שמכיל הפנייה לאובייקט של Revision שהוא עצמו השתנה. אתה יכול ליצור העתקה עמוקה של הRevision כדי לדעת מה היה המצב בעת ההרצה גם אם ישתנו דברים אבל כל זה לא קשור לדעתי לשגיאה.אם יש לך קובץ דמה אשמח לנסות אצלי.
פורסם במקור בפורום CODE613 ב21/08/2017 13:26 (+03:00)
-
אגב כדי להזים את חששותיך נסה ללא yield וlinq בכלל:
var revisions = doc.Revisions.Cast<word.Revision>().ToList(); var revList = new List<revsInOrder>(); revList.Add(new revsInOrder { prev = null, next = revisions[1], current = revisions[0] }); for (int i = 1; i < revisions.Count - 1; i++) revList.Add(new revsInOrder { prev = revisions[i - 1], next = revisions[i + 1], current = revisions[i] }); revList.Add(new revsInOrder { prev = revisions[revisions.Count - 2], next = null, current = revisions[revisions.Count - 1] }); for (int i = 0; i < revisions.Count; i++) if (revisions[i].next?.Range.Start == revisions[i].current.Range.End) { revisions[i].current.Accept(); revisions[i].next.Accept(); }
פורסם במקור בפורום CODE613 ב21/08/2017 13:35 (+03:00)
-
ומה אתה אומר על זה שאחרי שאני מקבל שינוי כל שהוא האינדקס של כל שאר השינויים משתנה ואז הוא לא מזהה את זה בגלל שהאובקט בצורתו כבר לא קיים? וזה יכול להיות גם בליסט. ולכן סדרתי את זה לפי האינדקס שהוא יקבל ויוריד מהרשימה רק את האחרונים ואז האינדקס של הראשונים לא ישתנה. כל זאת בגלל שאין לכל אוביקט שם ID כמו במקומות אחרים לכן צריך לזהות אותו באופנים אחרים. האם החשש קיים, ואם לא פה אולי במקומות אחרים שצריך לשים לב לזה?
פורסם במקור בפורום CODE613 ב21/08/2017 13:53 (+03:00)
-
אינני מצוי בנבכי הrevision של וורד, וגם אינני מבין אותך: "אחרי שאני מקבל שינוי כל שהוא האינדקס של כל שאר השינויים משתנה ואז הוא לא מזהה את זה בגלל שהאובקט בצורתו כבר לא קיים?" - לא הבנתי את המשפט אם כי אני מבין שאתה מציב שאלה מה עם האינדקסים שמשתנים כמו מפולת אחרי הוספת תוים במסמך. אבל לא הבנתי האם השינוי משתקף באובייקטים או לא, וגם מה הבעיה הסבוכה שזה מביא.
וגם, עדיין לא הבאת שגיאה.
פורסם במקור בפורום CODE613 ב21/08/2017 14:53 (+03:00)
-
אכן.
זה עובד גם בלי לינק, וגם עם לינק אבל אחרי המון המון זמן, הוא מקבל שינוי אחד או שנים ואחרי זה פולט שגיאה כזו:האובייקט המבוקש אינו זמין.
וכעת אני מבין שזה בגלל שהיה אי אילו שינויים באוביקטים עצמם ולכן הוא לא מזהה את האובקטי הקיים באוסף מפני שהוא השתנה.
ואמנם ההפניה אליו קיימת ברשימה אבל הוא עצמו לא קיים במסמך ולכן אי אפשר לקבל אותו או לעשות איתו משהו. זה כמו פסקה ששנמחקה פתאום.(ואגב האינדקסים בוורד ובאינדיזיין C# מתחילים ב1)
פורסם במקור בפורום CODE613 ב21/08/2017 19:00 (+03:00)
-
בסוף הסאגה, מתברר שבתנאי היה צריך לבדוק על אוביקטים שכבר נמחקו מכיון שההשואה שלהם התקבלה, ולכן הם לא היו בכלל קימים. ומה שמענין הוא שאת האוביקט עצמו כלומר ההשואה עצמה הוא כן מזהה אבל לא את התכונות שלה. כלומר אם אני בודק אם הוא קיים הוא מחזיר שכן, אבל אין גישה לפרופרטיז, אולי קשור לGB.
בכל אופן עשיתי משהו אחר, לאור כל הנ"ל, פשוט עשיתי רשימה טובה כמו שהתבאר לעיל. אחרי זה בדקתי את התנאים, והכנסתי את האינדקס של כל אחד מהם לרשימה. אחרי זה, כדי שלא לפול בפח הזה של שינוי האינדקזים הפכתי את סדר הרשימה.
וכעת אני מריץ על הרשימה הזו את הדחיה והקבלה. וככה האינדקס שמפנה הוא מהאחרונים ולכן הוא לא משנה את הסדר של הראשונים.
זה נראה משהו כזה ב
revList.Add(new revsInOrder { prev = revisions[revisions.Count - 2], next = null, current = revisions[revisions.Count - 1] });List<int> intList = new List<int>(); for (int i = revList.Count-3; i > 0; i--) { if (revList[i].next.Range.Start == revList[i].current.Range.End) { intList.Add(revList[i].current.Index); } } intList.OrderByDescending(p=>p); foreach (var item in intList) { doc.Revisions[item].Accept(); }
פורסם במקור בפורום CODE613 ב21/08/2017 23:42 (+03:00)