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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.