Home > Net >  Javascript element count in an array (based on a condition)
Javascript element count in an array (based on a condition)

Time:04-15

I am working on an LMS project where the end-user will click on a check box indicating a particular lesson is marked as complete. based on the number of lessons marked as completed, I need to showcase the percentage of course completion.

If there are 6 lessons and the user marked 3 lessons as completed, the math is 3/6 *100 = 50%.

Below is how my input JSON document looks like

[
    {
        "__typename": "ps_lessons",
        "lesson_id": 1,
        "id": "c9243c5b-2bf4-4afd-ab75-5fb7587b0d4f",
        "lesson_title": "Lesson 1",
        "multi_learners": [
            {
                "__typename": "ps_lesson_learners",
                "id": "5567c2a2-e0ff-4015-9bc6-a472b7683b01",
                "lesson_id": "c9243c5b-2bf4-4afd-ab75-5fb7587b0d4f",
                "check": true
            }
        ],
    },
    {
        "__typename": "ps_lessons",
        "lesson_id": 2,
        "id": "e3a26cc4-793e-4e56-bd30-c14a15633e5f",
        "lesson_title": "Lesson 2",
        "multi_learners": [
            {
                "__typename": "ps_lesson_learners",
                "id": "246e47e6-1821-4aae-9e2a-7abfd848ad4b",
                "lesson_id": "e3a26cc4-793e-4e56-bd30-c14a15633e5f",
                "check": true
            }
        ],
    },
    {
        "__typename": "ps_lessons",
        "lesson_id": 3,
        "id": "981e53c6-a63c-4a6f-84df-286c356b6a41",
        "multi_learners": [
            {
                "__typename": "ps_lesson_learners",
                "id": "52f44453-eb6a-4694-ba38-cfb6f96ab50d",
                "lesson_id": "981e53c6-a63c-4a6f-84df-286c356b6a41",
                "check": false
            }
        ],
    },
    {
        "__typename": "ps_lessons",
        "lesson_id": 4,
        "id": "88a7c331-0029-451e-b408-d35fbfd8f3f9",

    },
      {
        "__typename": "ps_lessons",
        "lesson_id": 5,
        "id": "88a7c331-0029-451e-84df-286c356b6a41",
    }
    
]

in the above document there are a total of 5 ps_lessons elements are there for every element there is a sub-element ps_lesson_learners where multi_learners[0].check indicates the user's selection.

So I need to figure it out, if there is a subelement i.e. ps_lesson_learners if the subelement is present then check the true value for multi_learners[0].check and divide it with the total lessons and multiply by 100 to get the percentage.

there are a total of 2 true status out of 5 lessons so it will be 2/5 * 100 = 40%

I tried some thing like below with map method and coudln't able to get the result

  data.map((data)=>{
    if (data.multi_learners.length == 1) {
      if (data.multi_learners[0].check == 'true') {
        count = count   1;
      }
    }
  });

  final_count = count * data.length/100

Appreciate your help with the code.

Thanks Venk

CodePudding user response:

You could use Array.filter() to count the number of completed lessons:

let input = [ { "__typename": "ps_lessons", "lesson_id": 1, "id": "c9243c5b-2bf4-4afd-ab75-5fb7587b0d4f", "lesson_title": "Lesson 1", "multi_learners": [ { "__typename": "ps_lesson_learners", "id": "5567c2a2-e0ff-4015-9bc6-a472b7683b01", "lesson_id": "c9243c5b-2bf4-4afd-ab75-5fb7587b0d4f", "check": true } ], }, { "__typename": "ps_lessons", "lesson_id": 2, "id": "e3a26cc4-793e-4e56-bd30-c14a15633e5f", "lesson_title": "Lesson 2", "multi_learners": [ { "__typename": "ps_lesson_learners", "id": "246e47e6-1821-4aae-9e2a-7abfd848ad4b", "lesson_id": "e3a26cc4-793e-4e56-bd30-c14a15633e5f", "check": true } ], }, { "__typename": "ps_lessons", "lesson_id": 3, "id": "981e53c6-a63c-4a6f-84df-286c356b6a41", "multi_learners": [ { "__typename": "ps_lesson_learners", "id": "52f44453-eb6a-4694-ba38-cfb6f96ab50d", "lesson_id": "981e53c6-a63c-4a6f-84df-286c356b6a41", "check": false } ], }, { "__typename": "ps_lessons", "lesson_id": 4, "id": "88a7c331-0029-451e-b408-d35fbfd8f3f9",  }, { "__typename": "ps_lessons", "lesson_id": 5, "id": "88a7c331-0029-451e-84df-286c356b6a41", }  ]

function getCompletedCount(input) {
    return input.filter(input => input.multi_learners &&
        input.multi_learners[0] &&
            input.multi_learners[0].check).length;
}

console.log('Completed count:', getCompletedCount(input))
console.log('Completed %:', 100*getCompletedCount(input)/input.length)
.as-console-wrapper { max-height: 100% !important; }

You can also use Optional chaining if your environment allows it (e.g. Chrome version >= 80, Node version >= 14.0)

let input = [ { "__typename": "ps_lessons", "lesson_id": 1, "id": "c9243c5b-2bf4-4afd-ab75-5fb7587b0d4f", "lesson_title": "Lesson 1", "multi_learners": [ { "__typename": "ps_lesson_learners", "id": "5567c2a2-e0ff-4015-9bc6-a472b7683b01", "lesson_id": "c9243c5b-2bf4-4afd-ab75-5fb7587b0d4f", "check": true } ], }, { "__typename": "ps_lessons", "lesson_id": 2, "id": "e3a26cc4-793e-4e56-bd30-c14a15633e5f", "lesson_title": "Lesson 2", "multi_learners": [ { "__typename": "ps_lesson_learners", "id": "246e47e6-1821-4aae-9e2a-7abfd848ad4b", "lesson_id": "e3a26cc4-793e-4e56-bd30-c14a15633e5f", "check": true } ], }, { "__typename": "ps_lessons", "lesson_id": 3, "id": "981e53c6-a63c-4a6f-84df-286c356b6a41", "multi_learners": [ { "__typename": "ps_lesson_learners", "id": "52f44453-eb6a-4694-ba38-cfb6f96ab50d", "lesson_id": "981e53c6-a63c-4a6f-84df-286c356b6a41", "check": false } ], }, { "__typename": "ps_lessons", "lesson_id": 4, "id": "88a7c331-0029-451e-b408-d35fbfd8f3f9",  }, { "__typename": "ps_lessons", "lesson_id": 5, "id": "88a7c331-0029-451e-84df-286c356b6a41", }  ]

function getCompletedCount(input) {
    return input.filter(input => input?.multi_learners?.[0]?.check).length;
}

console.log('Completed count:', getCompletedCount(input))
console.log('Completed %:', 100*getCompletedCount(input)/input.length)
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

.map() is not what you are looking for as it returns an array with each element in the output corresponding to each of the input. You can use .reduce() instead:

data.reduce((count, each) => count each.multi_learners?.length == 1 && each.multi_learners[0].check == 'true' ? 1 : 0, 0)

or instead of using a ternary, cast the boolean as Number:

data.reduce((count, each) => count Number(each.multi_learners?.length == 1 && each.multi_learners[0].check == 'true'), 0)

This doesn't incur two loops of first filtering then counting the length of those that survived the filter.

  • Related