1

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

1
  • Not all the objects have the "multi-learners" property, you should make sure that your data structure is homogeneous. Commented Apr 15, 2022 at 11:09

4 Answers 4

2

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; }

Sign up to request clarification or add additional context in comments.

Comments

1

You could also use a forEach:

var jsondata = [ { "__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", }  ];

const getStatus = (jsondata) => {
    let items = 0
    let hasCheckTrue = 0

    // count items and check for checks
    jsondata.forEach(item => {
        items++
        if (item.multi_learners && item.multi_learners[0].check){
            hasCheckTrue++
        }
    })

    // do calc
    let complete = (hasCheckTrue / items * 100)

    // probably want to return something better than this here
    let result = `${items} items, ${hasCheckTrue} completed = ${complete}%`
    return result
}

// call func with data
console.log(getStatus(jsondata))

Comments

0

.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.

Comments

0

Another way is to use reduce(), with the initial value of 100 (%), and reduce the percentage with 100 / data.length for each non-valid object:

const data = [ { "__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", }  ];

const checkedProcent = data.reduce((prev, cur) => {
  if (!cur.multi_learners?.[0].check) {
      prev -= (100 / data.length);
  }
  return prev;
}, 100);

console.log(checkedProcent + '%');

40%

Or as a compact one-liner:

data.reduce((p, c) => (c.multi_learners?.[0].check) ? p : (p - (100 / data.length)), 100);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.