דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. ארכיון code613m
  4. JS: uniq על מערך של אובייקטים

JS: uniq על מערך של אובייקטים

מתוזמן נעוץ נעול הועבר ארכיון code613m
18 פוסטים 4 כותבים 1.2k צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • A מנותק
    A מנותק
    avr416
    כתב ב נערך לאחרונה על ידי
    #1

    מישהו מוכן להסביר לי מדוע הקוד הבא לא עובד???
    כלומר, הוא עובד, אבל מחזיר לי את כל האובייקטים חזרה למרות ששלושה מהם הם כפולים?

    var array = [{id:15, name: "עברית"},{id:15, name: "עברית"},{id:15, name: "עברית"},{id:16, name: "תורה"}]
    var uniqArr = array.filter(function (v, i, arr) {
                            return arr.indexOf(v) === i
                        })
    console.log(uniqArr)
    

    הנה קישור לקודפן שם אפשר לראות את הקוד בפעולה (בקונסולה כמובן) <!-- s:-) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":-)" title="מחייך" /><!-- s:-) -->

    אם התשובה היא בגלל שלעולם כל אובייקט שונה מחברו, גם אם המפתחות (זה המילה בעברית :lol: ) אותו דבר.. אז היש דרך מהירה ופשוטה לעשות uniq על אובייקטים? או שמא צריך לרוץ בלולאה ולנסות להשוות keys??

    תודה מראש!

    פורסם במקור בפורום CODE613 ב19/07/2017 23:22 (+03:00)

    תגובה 1 תגובה אחרונה
    0
    • A מנותק
      A מנותק
      avr416
      כתב ב נערך לאחרונה על ידי
      #2

      https://stackoverflow.com/questions/20739575/how-can-i-get-a-unique-array-based-on-object-property-using-underscore

      בלי שימוש בספריות חיצוניות, אפשר גם כך:

      var array = [{id:15, name: "עברית"},{id:15, name: "עברית"},{id:15, name: "עברית"},{id:16, name: "תורה"}]
      var uniqArr = [array[0]]
      for(var i =0;i<array.length;i++){
        if(!hasEqual(array[i], uniqArr))
          uniqArr.push(array[i])
      }
      function hasEqual(obj, arr) {
        for (i=arr.length;i--;)
           if (hasObjEqual(obj, arr[i])) return true
        return false
      }
      function hasObjEqual(obj, thisObj) {
         for (var prop in obj)
            if (obj[prop] !== thisObj[prop]) return false
         return true 
      } 
      console.log(uniqArr)
      

      https://codepen.io/avrahamAhituv/pen/VWJgRZ

      פורסם במקור בפורום CODE613 ב20/07/2017 00:06 (+03:00)

      תגובה 1 תגובה אחרונה
      0
      • רחמיםר מנותק
        רחמיםר מנותק
        רחמים מורחק
        כתב ב נערך לאחרונה על ידי
        #3

        תשתמש בפונקציה:
        object.Keys

        פורסם במקור בפורום CODE613 ב20/07/2017 00:13 (+03:00)

        תגובה 1 תגובה אחרונה
        1
        • dovidD מנותק
          dovidD מנותק
          dovid ניהול
          כתב ב נערך לאחרונה על ידי
          #4

          איזה שאלה יפה, והקוד שלה גם מוצלח ומבריק. ולמה זה לא עובד? כי indexOf עובד באובייקטים לפי זהות (האם זה האובייט הזה ממש עם אותו מצביע בזיכרון, מה שנקרא בדוטנט RefrenceEqual) ולא לפי השוואה ערכי המאפיינים. וזה גם טוב וברור שכך זה אמור להיות.
          קודם כל הבעיה הקלאסית זה כשרוצים לפי מאפיין בודד שמהווה זיהוי של האובייקט, גם זה די קשה.
          יש מתודה חדשה () שמה findIndex שמקבלת כפרמטר פונקציה שהיא פרדיקייט למה שמחפשים, למשל
          [{"a": "bla bla bla"}, {"a": "bla bla"}].findIndex(x => x.a == "bla bla bla").
          לפני כן מה שהיו עושים זה שימוש בmap שיוצר עותק של המערך עם חילוץ/יצירה שלערך עבור כל ערך מקור בהתאמה, ואז בוחרים לחילוץ את הערך הרצוי (למשל תז) או קומבינציה של הרצויים (זה יכול להיות אפי' כולם ע"י JSON.stringify) ואז את החיפוש עושים מול המערך השני:

          var arrObj = [{"a": "bla bla bla"}, {"a": "bla bla"}];
          var arrForSearch = arrObj.map(x => x.a);  //["bla bla bla", "bla bla"]
          var foundedIndex = arrForSearch.indexOf("bla bla bla");
          

          זה פותר את הבעיה של זהות פר מאפיין אבל עדיין לא השוואה מול כלל המאפיינים והקוד שהבאת עושה זאת מצויין אם כי אני חושב שזה מצב שעדיף למנוע וגם זה לא מכסה כל מקרה למשל מאפיינים לא זהים שבאחד יש ובשני אין. הfinsIndex/map+indexOf בשילוב עם JSON.stringify זה מכסה הכל אבל זה מחריד לעבוד ככה..

          פורסם במקור בפורום CODE613 ב20/07/2017 01:41 (+03:00)

          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

          בכל נושא אפשר ליצור קשר dovid@tchumim.com

          תגובה 1 תגובה אחרונה
          1
          • dovidD מנותק
            dovidD מנותק
            dovid ניהול
            כתב ב נערך לאחרונה על ידי
            #5

            אגב תחשוב, מה היית עושה עם linq? גם שם זה לא פשוט. השוואה לפי כלל המאפיינים קיימת בהשוואת struct, אבל במחלקות אין ברירה חוץ מרפלקשיין. כמובן תמיד ניתן להכין באובייקט מתודת השוואה ו/או לדרוס את הGetHashCode או להשתמש בIComparer וכו'.
            אגב ראיתי כשמונה ספריות פופולריות של linq בjs ולבטח יש עוד הרבה...

            פורסם במקור בפורום CODE613 ב20/07/2017 02:06 (+03:00)

            מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

            בכל נושא אפשר ליצור קשר dovid@tchumim.com

            תגובה 1 תגובה אחרונה
            1
            • A מנותק
              A מנותק
              avr416
              כתב ב נערך לאחרונה על ידי
              #6

              @דוד ל.ט.

              אגב תחשוב, מה היית עושה עם linq? גם שם זה לא פשוט. השוואה לפי כלל המאפיינים קיימת בהשוואת struct, אבל במחלקות אין ברירה חוץ מרפלקשיין. כמובן תמיד ניתן להכין באובייקט מתודת השוואה ו/או לדרוס את הGetHashCode או להשתמש בIComparer וכו'.
              אגב ראיתי כשמונה ספריות פופולריות של linq בjs ולבטח יש עוד הרבה...

              עוד לא יצא לי שהייתי צריך להשתמש בדבר כזה..

              פשוט אני מקבל דטה שהיא מערך של שיעורים, ואני צריך להגיע למצב של ליסט רק של השיעורים שלא כפולים, מאידך אני צריך גם את שאר המידע שיש על כל שיעור, כגון המזהה שלו (לצורך החיפוש אח"כ) ועוד פרמטרים.

              לפי מה שכתבת אז אני חושב שהיה אפשר גם לכתוב ככה, כדי להשיג אח"כ גם את התוכן:

              var array = [{id:15, name: "עברית"},{id:15, name: "עברית"},{id:15, name: "עברית"},{id:16, name: "תורה"}]
              var uniq = array.map(x=>x.name).filter((v,i,arr) => arr.indexOf(v) ===i )   
              var uniqArr = uniq.map(x => array[array.findIndex(y => y.name === x.name)])
              
              console.log(uniq) 
              console.log(uniqArr)
              

              אבל משום מה זה לא עובד..
              כלומר הוא יוצר לי מערך ייחודי רק של הname. אולם, אח"כ הוא מחזיר לי כאילו השם הזה לא קיים במערך המקורי. -1
              אא"כ אני כותב לו את השם המפורש 🙂 דהיינו =='עברית' ואז אכן הוא מחזיר לי את האינדקס.. אלא שכמובן שאני לא יודע מה יהיה אותו תוכן..

              פורסם במקור בפורום CODE613 ב20/07/2017 10:26 (+03:00)

              תגובה 1 תגובה אחרונה
              0
              • dovidD מנותק
                dovidD מנותק
                dovid ניהול
                כתב ב נערך לאחרונה על ידי
                #7

                אם אתה משתמש בfindIndex אז אתה יכול לשכוח מהmap.
                בשורה שתיים עשית מצויין אבל א. זה מסנן רק לפי הname ב. אתה צריך להוציא את האינדקסים של המקור, והmap מפסיד אותם לגמרי כפי שכתבת.
                אם אתה מחפש רק לפי השם או אפי' אם לפי שתי המאפיינים ולא "איך אני משווה את כל המאפיינים" אז נורא פשוט. עם findIndex:

                var array = [{id:15, name: "עברית"},{id:15, name: "עברית"},{id:15, name: "עברית"},{id:16, name: "תורה"}];
                var uniqArr = array.filter((item, index) => array.findIndex(x => x.name == item.name) == index);
                                    
                console.log(uniqArr);
                

                ואם ע"י הmap, ובהנחה שדרוש רק השוואת מאפיין name, אז ככה:

                var array = [{id:15, name: "עברית"},{id:15, name: "עברית"},{id:15, name: "עברית"},{id:16, name: "תורה"}];
                var arrForIndexs = array.map(x => x.name);
                var uniqArr = array.filter((item, index) => arrForIndexs.indexOf(item.name) == index);
                console.log(uniqArr);
                

                פורסם במקור בפורום CODE613 ב20/07/2017 14:03 (+03:00)

                מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                בכל נושא אפשר ליצור קשר dovid@tchumim.com

                תגובה 1 תגובה אחרונה
                1
                • dovidD מנותק
                  dovidD מנותק
                  dovid ניהול
                  כתב ב נערך לאחרונה על ידי
                  #8

                  אגב, מי שעושה כאלה מוניפולציות בקוד יותר מפעם אחת חייב חייב להשתמש בunderscore.
                  לא בשביל חיסכון הזמן (כי בכל מקרה שורפים זמן איך לעשות בunserscore...) אלא בשביל נאמנות הקוד וקלות תחזוקו.
                  אני יודע שנמאס להוסיף עוד ועוד תלויות אבל underscore נחוץ כל שתי שורות קוד שקשורים למערך.

                  פורסם במקור בפורום CODE613 ב20/07/2017 14:21 (+03:00)

                  מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                  בכל נושא אפשר ליצור קשר dovid@tchumim.com

                  תגובה 1 תגובה אחרונה
                  1
                  • רחמיםר מנותק
                    רחמיםר מנותק
                    רחמים מורחק
                    כתב ב נערך לאחרונה על ידי
                    #9

                    תבדוק את זה:
                    https://codepen.io/anon/pen/WOVRBg?editors=1112

                    var array = [{id:15, name: "עברית"},
                                 {id:15, name: "עברית"},
                                 {id:15, name: "עברית"},
                                 {id:16, name: "תורה"}]
                    var uniq = {};
                    array.forEach(function(i) {
                        uniq[i.id] = i;
                    });
                    console.log(uniq);
                    

                    פורסם במקור בפורום CODE613 ב20/07/2017 16:13 (+03:00)

                    תגובה 1 תגובה אחרונה
                    1
                    • dovidD מנותק
                      dovidD מנותק
                      dovid ניהול
                      כתב ב נערך לאחרונה על ידי
                      #10

                      רחמים פתרון יפה, אבל אם כבר לפי איבר מסויים אז הבנתי שזה הname רק שצריך את המאפיין גם של הID. אז אם ככה uniq[i.name].
                      וavr416 פעם הבאה חוץ מהבעיה תסביר מה המטרה הרצוייה, והם שייך מקרה של id שונה ושם זהה ומה הדין בכהאי גונא ומדוע 🙂

                      פורסם במקור בפורום CODE613 ב20/07/2017 17:41 (+03:00)

                      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                      בכל נושא אפשר ליצור קשר dovid@tchumim.com

                      תגובה 1 תגובה אחרונה
                      2
                      • רחמיםר מנותק
                        רחמיםר מנותק
                        רחמים מורחק
                        כתב ב נערך לאחרונה על ידי
                        #11

                        הפתרון שכתבתי לעיל עדיף משמעותית מבחינת מהירות [פי 20] על פני שימוש במערך רגיל.
                        ראה ניסוי כאן
                        http://jsben.ch/GYK6P

                        פורסם במקור בפורום CODE613 ב20/07/2017 19:05 (+03:00)

                        תגובה 1 תגובה אחרונה
                        1
                        • A מנותק
                          A מנותק
                          avr416
                          כתב ב נערך לאחרונה על ידי
                          #12

                          @דוד ל.ט.

                          רחמים פתרון יפה, אבל אם כבר לפי איבר מסויים אז הבנתי שזה הname רק שצריך את המאפיין גם של הID. אז אם ככה uniq[i.name].
                          וavr416 פעם הבאה חוץ מהבעיה תסביר מה המטרה הרצוייה, והם שייך מקרה של id שונה ושם זהה ומה הדין בכהאי גונא ומדוע 🙂

                          רחמים כל הכבוד על הפתרון הפשוט!!
                          דוד, תודה ענקית על ההסברים, אם כי עדיין לא הבנתים לגמרי.

                          אבאר קצת יותר, אני בונה דוח שמאפשר למשתמש להציג את התוצאות של כל המבחנים שהתקיימו בתקופה מסויימת, במקצוע מסויים לבחירתו.
                          אני מאפשר לו לבחור עבור אילו כיתות או שכבות הוא רוצה להציג את התוצאות, ואני רוצה להציג את המקצוע רק כאשר קיימים עבורו מבחנים באותה תקופה.
                          לכן, אני בודק בדטה בייס, באילו מקצועות התקיימות מבחנים בתאריכים הללו, לאותם כיתות, ורק אז אני מציג את שם המקצוע בסלקטבוקס.
                          הענין הוא שכיון שהוא יכול לבחור כמה כיתות, אז הנתונים שאני מקבל מהדטה בייס שונים בהרבה פרטים שלא כ"כ משמעותיים כרגע עבורי, ומה שמעניין אותי זה רק באיזה מקצוע התקיים המבחן, דהיינו הID של המקצוע, וגם השם שלו (כדי להציג למשתמש).
                          הID והName הם תמיד זהים, ולא משתנים. מה שכן משתנה זה הרבה דברים אחרים, למשל איזה כיתה, איזה מורה וכו'.

                          @דוד ל.ט.

                          אם אתה משתמש בfindIndex אז אתה יכול לשכוח מהmap.
                          בשורה שתיים עשית מצויין אבל א. זה מסנן רק לפי הname ב. אתה צריך להוציא את האינדקסים של המקור, והmap מפסיד אותם לגמרי כפי שכתבת.
                          אם אתה מחפש רק לפי השם או אפי' אם לפי שתי המאפיינים ולא "איך אני משווה את כל המאפיינים" אז נורא פשוט. עם findIndex:

                          מעולה!! באמת לא הבנתי כ"כ איך התכוונת עם הfindIndex הרי לא מעניין אותי כ"כ האינדקס, אלא מעניין אותי שייתן לי את המערך הuniq.
                          למה הmap הורס את האינדקסים של המערך המקורי? הרי הוא לא משנה את המקור, הוא בסה"כ מחזיר מערך חדש ע"פ התנאי שאני מעביר לו, לא?
                          אז אם כן, מה הבעיה שתוך כדי הmap הוא גם ירוץ על המקורי ויחזיר לי את האינדקס שלו??

                          תודה רבה רבה!

                          פורסם במקור בפורום CODE613 ב20/07/2017 20:47 (+03:00)

                          תגובה 1 תגובה אחרונה
                          0
                          • dovidD מנותק
                            dovidD מנותק
                            dovid ניהול
                            כתב ב נערך לאחרונה על ידי
                            #13

                            @רחמים

                            הפתרון שכתבתי לעיל עדיף משמעותית מבחינת מהירות [פי 20] על פני שימוש במערך רגיל.
                            ראה ניסוי כאן
                            http://jsben.ch/GYK6P

                            אין ספק שהפתרון שלך יעיל יותר. במקום לסרוק, דורסים לפי אינדקס שלא מתבצע ע"י סריקה אלא ע"י הצבה לאינדקס של אובייקט (שממומש ע"י מילון של hash table). את זה יודעים בלי שום טסט (שאגב עם המון פגמים).
                            אבל איך עושים אם רוצים להשוות לפי שתי מאפיינים? אולי אפשר פשוט לשרשר אותם, לדעתי זה גם יהיה מהר יותר כשהמערך גדול.

                            פורסם במקור בפורום CODE613 ב20/07/2017 21:09 (+03:00)

                            מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                            בכל נושא אפשר ליצור קשר dovid@tchumim.com

                            תגובה 1 תגובה אחרונה
                            1
                            • dovidD מנותק
                              dovidD מנותק
                              dovid ניהול
                              כתב ב נערך לאחרונה על ידי
                              #14

                              יאהוו הארכת. במילים אחרות באובייקטים יחודיים לפי הID. נקודה.
                              הפתרון של רחמים הוא בהחלט המתאים, אם כי הקוד בשאלה היה יפה ומבריק וטרחתי להעמידו על רגליו.
                              לא מבין מה לא הבנת כי שמתי שפע דוגמאות קוד, ובנוגע לmap הוא מחזיר לך מערך חדש, אבל איללו חשוב לך האיברים המקוריים אין מי שיעשה לך את ההקשר בין האיבר המקורי לאיבר שנשלף ע"י הmap.
                              כמובן כל זה לולי שידעתי שהקובע הוא אך ורק הid.

                              פורסם במקור בפורום CODE613 ב20/07/2017 21:13 (+03:00)

                              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                              בכל נושא אפשר ליצור קשר dovid@tchumim.com

                              תגובה 1 תגובה אחרונה
                              1
                              • רחמיםר מנותק
                                רחמיםר מנותק
                                רחמים מורחק
                                כתב ב נערך לאחרונה על ידי
                                #15

                                @דוד ל.ט.

                                @רחמים
                                הפתרון שכתבתי לעיל עדיף משמעותית מבחינת מהירות [פי 20] על פני שימוש במערך רגיל.

                                ראה ניסוי כאן
                                http://jsben.ch/GYK6P

                                אין ספק שהפתרון שלך יעיל יותר. במקום לסרוק, דורסים לפי אינדקס שלא מתבצע ע"י סריקה אלא ע"י הצבה לאינדקס של אובייקט (שממומש ע"י מילון של hash table). את זה יודעים בלי שום טסט (שאגב עם המון פגמים).
                                אבל איך עושים אם רוצים להשוות לפי שתי מאפיינים? אולי אפשר פשוט לשרשר אותם, לדעתי זה גם יהיה מהר יותר כשהמערך גדול.

                                זהו שלא היה ברור לי כלל שאובייקט בJS מאחורי הקלעים הוא בעצם טבלת האש ולא סתם מערך, הניסוי הנ"ל נבנה כדי לפשוט ספק זה.
                                אגב, איזה פגמים מצאת בניסוי?

                                פורסם במקור בפורום CODE613 ב20/07/2017 21:19 (+03:00)

                                תגובה 1 תגובה אחרונה
                                0
                                • dovidD מנותק
                                  dovidD מנותק
                                  dovid ניהול
                                  כתב ב נערך לאחרונה על ידי
                                  #16

                                  לא המון, אלא משהו משמעותי שקפץ לי. הרי אתה רצית להשוות את הסריקה של מערך לבין סריקה של אובייקט, כלומר:

                                  arr.indexOf(x)
                                  VS
                                  object[x]
                                  

                                  אז דבר ראשון בטסט שלך מאוד משמעותי מה קורה אחרי הסריקה. בתצורת המערך אז מכניסים למערך איבר, זה נקודה יקרה מאוד אבל רצית להמחיש את פחיתותו של הפתרון הראשון אבל זה מטשטש את מה שאתה רצית לדעת.
                                  שנית, בעוד שבתצורת המערך העתקת את האובייקטים (כל אחד שמופיע בout מופיע בנפרד גם במקור), אז בתצורת האובייקט השמת ערך בולאני שהוא פרמיטיבי וחוסך מצביע וכתיבת האובייקט כולו.

                                  פורסם במקור בפורום CODE613 ב20/07/2017 21:29 (+03:00)

                                  מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                                  בכל נושא אפשר ליצור קשר dovid@tchumim.com

                                  תגובה 1 תגובה אחרונה
                                  0
                                  • M מנותק
                                    M מנותק
                                    magicode
                                    כתב ב נערך לאחרונה על ידי
                                    #17

                                    דוד הנה תיקון לטסט. וזה לא משנה את התוצאה.
                                    http://jsben.ch/Iqxce

                                    פורסם במקור בפורום CODE613 ב21/07/2017 08:49 (+03:00)

                                    תגובה 1 תגובה אחרונה
                                    1
                                    • dovidD מנותק
                                      dovidD מנותק
                                      dovid ניהול
                                      כתב ב נערך לאחרונה על ידי
                                      #18

                                      לא חשבתי שזה ישנה, רק צריך לעשות טסט כמו שצריך. כדי ללמוד בדיוק את הנקודה.

                                      פורסם במקור בפורום CODE613 ב21/07/2017 10:18 (+03:00)

                                      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                                      בכל נושא אפשר ליצור קשר dovid@tchumim.com

                                      תגובה 1 תגובה אחרונה
                                      0

                                      בא תתחבר לדף היומי!
                                      • התחברות

                                      • אין לך חשבון עדיין? הרשמה

                                      • התחברו או הירשמו כדי לחפש.
                                      • פוסט ראשון
                                        פוסט אחרון
                                      0
                                      • דף הבית
                                      • קטגוריות
                                      • פוסטים אחרונים
                                      • משתמשים
                                      • חיפוש
                                      • חוקי הפורום