0

There are many posts on counting unique values in arrays, but I want to count the unique values in an array based on a second array. Specifically: I want to count the distinct occurrences within arr, but of all the values within grade

arr = [
  "12D","12D","12D",
  "12C","12C","12C","12C","12C",
  "12B","12B","12B","12B","12B",
  "12B","12B",
  "12A","12A","12A","12A","12A",
  "12A","12A","12A","12A","12A",
  "12A","12A"
]

grade = ["13B", "13A", "12D", "12C", "12B", "12A"]

result = arr.filter(item => grade.includes(item))
  .reduce((acc, val) => {
    acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
    return acc;
  }, {});

Current Result

My current result does count up the unique occurances

{ '12D': 3, '12C': 5, '12B': 7, '12A': 12 }

Desired Output

but I want to include ALL the values within grade inside my final object (and in the order of grade]

desired_result = {
    '13B': 0,
    '13A': 0,
    '12D': 3,
    '12C': 5,
    '12B': 7,
    '12A': 12
}

Is it possible to perform this reduce using a second vector?

1
  • I think some context is missing but if thats the whole thing, I would go at it from another direction, I would first convert the "grade" array to an object with all 0 as a value and key would be the grade from array. Then run on "arr" and just add the counter where it fits. Commented Nov 21, 2021 at 16:20

2 Answers 2

1

Another approach would be to start off with the grades and build a frequency table as follows. Then you can invoke Object.fromEntries() on the resulting array of array pairs:

const result = Object.fromEntries(
    grade.map(grade => [grade, arr.filter(g => g === grade).length])
);

DEMO

const arr = ["12D","12D","12D","12C","12C","12C","12C","12C","12B","12B","12B","12B","12B","12B","12B","12A","12A","12A","12A","12A","12A","12A","12A","12A","12A","12A","12A"];

const grade = ["13B", "13A", "12D", "12C", "12B", "12A"];

const result = Object.fromEntries(
    grade.map(grade => [grade, arr.filter(g => g === grade).length])
);

console.log( result );

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

Comments

1

You could map grades as entries and take the object as start value of reduce.

const
    array = ["12D", "12D", "12D", "12C", "12C", "12C", "12C", "12C", "12B", "12B", "12B", "12B", "12B", "12B", "12B", "12A", "12A", "12A", "12A", "12A", "12A", "12A", "12A", "12A", "12A", "12A", "12A"],
    grade = ["13B", "13A", "12D", "12C", "12B", "12A"],
    result = array.reduce(
        (acc, val) => {
            if (val in acc) acc[val]++;
            return acc;
        },
        Object.fromEntries(grade.map(g => [g, 0]))
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

2 Comments

Not sure if it's critical to OP but doesn't filter out values that aren't in grade. Example doesn't have any but real cases may do
@charlietfl, now it counts only known props.

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.