Obtaining the count of distinct values for a specific property in an array of objects

I have a unique array structure as follows:

const uniqueArray = [
  { _id: '1', userId: '5' },
  { _id: '2', userId: null },
  { _id: '3', userId: null },
  { _id: '4', userId: '1' },
  { _id: '5', userId: '2' },
  { _id: '6', userId: '4' },
  { _id: '7', userId: '4' },
  { _id: '8', userId: null },
  { _id: '9', userId: null },
  { _id: '10', userId: '2' }
];

I would like to find out the total number of unique userId values. If a value is null, each occurrence should be counted separately. If a non-null userId value is repeated, it should only be counted once.

I attempted the function below, but it does not consider null values

const getUniqueCount = (arr, key) =>
  arr.reduce(
    (set, item) =>
      set.add(typeof key === "string" ? item[key] : key(item)),
    new Set()
  ).size;
getUniqueCount(uniqueArray, "userId");

Answer №1

To consolidate all the elements into a single output, you can utilize the .reduce() method.

const array = [
  { _id: '1', userId: '5' },
  { _id: '2', userId: null },
  { _id: '3', userId: null },
  { _id: '4', userId: '1' },
  { _id: '5', userId: '2' },
  { _id: '6', userId: '4' },
  { _id: '7', userId: '4' },
  { _id: '8', userId: null },
  { _id: '9', userId: null },
  { _id: '10', userId: '2' }
];

const {count} = array.reduce((acc, obj) => {
  if(acc.cache.includes(obj.userId)) return acc;
  
  if(obj.userId !== null) acc.cache.push(obj.userId);
  
  acc.count++;
  
  return acc;
}, {cache: [], count: 0});

console.log(count);

Answer №2

While it may not be the most efficient solution, for smaller original arrays, a simple approach would be to count the number of null values and unique non-null elements separately:

const numNulls = array.filter(x => x.userId === null).length;
const numUniqueNotNull = new Set(array.map(x => x.userId).filter(u => u !== null)).size
const totalSize = numNulls + numUniqueNotNull;

Answer №3

If you want to assign a unique identifier to the null values in the array, you can map them with their corresponding index.

new Set(array.map((item,index) => (item.userId === null ? `${item.userId}-${index}` : item.userId))).size

Answer №4

const items = [
  { _id: '1', userId: '5' },
  { _id: '2', userId: null },
  { _id: '3', userId: null },
  { _id: '4', userId: '1' },
  { _id: '5', userId: '2' },
  { _id: '6', userId: '4' },
  { _id: '7', userId: '4' },
  { _id: '8', userId: null },
  { _id: '19', userId: null },
  { _id: '10', userId: '2' }
];

const findUniqueItems = (list, key) => {
  let occurrences = {}; 
  let count = 0;
  items.map((item, index) => {
    count += typeof item[key] == "string" ? ((occurrences[item[key]]) ? 0 : 1) : 1;
    occurrences[item[key]] = 1;
  });
  return count;
};

console.log(findUniqueItems(items, "userId"));

Answer №5

Utilize Array.prototype.reduce() in conjunction with Set for an effective solution

Here is the code snippet:

const array = [
  { _id: '1', userId: '5' },
  { _id: '2', userId: null },
  { _id: '3', userId: null },
  { _id: '4', userId: '1' },
  { _id: '5', userId: '2' },
  { _id: '6', userId: '4' },
  { _id: '7', userId: '4' },
  { _id: '8', userId: null },
  { _id: '9', userId: null },
  { _id: '10', userId: '2' },
]

const { users, nulls } = array.reduce(
  (a, { userId: id }) => (id ? a.users.add(id) : a.nulls++, a),
  { users: new Set(), nulls: 0 }
)

console.log('Total:', users.size + nulls)

Answer №6

To achieve this, simply utilize .map alongside .reduce:

array.map(item => item.userId)
  .reduce((prev, cur) => !prev.includes(cur)? [...prev, cur]: prev, [])
  .length

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to show the existing value of a <select> in a label without altering the function

I currently have a label that changes to display the selected option from a dynamic select dropdown, but it only updates when the selection is changed. I would like it to also display the current value when the page first loads. I attempted to change &apos ...

Establishing a pre-selected option in a drop-down menu

I am working on a dropdown list and my goal is to have the default option selected when the page loads <b>Filter Within Months:</b> <select class="btn green" ng-model="myOptions" ng-options="i.label for i in items track by i.id" ng-change= ...

Change UL to a JSON format

I am attempting to transform an entire unordered list (UL) and its child elements into a JSON object. Here is the approach we took: function extractData(element) { element.find('li').each(function () { data.push({ "name": $(this).fi ...

Closing the nested accordion will collapse all sections within the accordion

I'm currently facing an issue with my nested accordions. I've been attempting to nest them in a way that doesn't require writing additional jQuery code for each new one added. As an example, I've created a jsfiddle... https://jsfiddle. ...

"Passing data from a child component to a parent component using Vue's emit

offspring template: ` <li v-for="option in listaOptiuni" :key="option.id"> <input @change="updateSelectAllToateOptiunile(); sendListaToateOptiunile()" v-model="listaToateOptiunile" :value="o ...

Leveraging OAuth 2 with Google

I'm currently working on implementing Google API for user authentication. I have successfully managed to authenticate users, but I am struggling with redirecting users after Sign In and implementing Sign Out functionality. I have been referring to th ...

Whenever I adjust the layout of the navigation bar, the edges end up getting clipped

I'm having trouble with the border shape of my navbar. When I try to make it a rounded pill shape, the edges get cut off instead of being properly displayed. https://i.stack.imgur.com/sUN2Y.png Below is the HTML template: <template> <div cl ...

Can you elaborate on the users object found in the npm registry JSON response?

When looking at the json response of any npm package, such as jQuery for example, http://registry.npmjs.org/jquery, you may come across a dictionary called users. This dictionary contains usernames as keys and boolean values as the corresponding values. ...

Organize divs based on their attributes

Using inspiration from this SO post, my goal is to group divs based on their "message-id" attribute. The idea is to wrap all divs with the same "message-id" in a div with the class name "group". <div class="message" message-id="1"> ...

Updating multiple subdocuments with Mongoose

My goal is to update a specific subdocument called addresses (which is working fine) and then update all other subdocuments except the one that was just changed. Whenever an address is changed to have is_preferred set to true, I need to update the previous ...

AngularJS secondary controller experiencing malfunctions

Having an issue with my second controller (RegisterController) in the module I've created. The first one is working perfectly fine. I have both controllers in a file named user.js var app = angular.module("User", []); app.controller('LoginCont ...

What's the reason behind the refusal of my connection to localhost at port 3000 in Node.JS?

As a student venturing into the world of back-end development for the first time, I decided to dive into learning Node.JS. To kick things off, I downloaded a PDF book titled "Jumpstart Node.JS" from SitePoint. Following the provided instructions, I attempt ...

Developing a specialized directive to enhance bootstrap menuItems

I have created a custom directive in AngularJS for the navbar in Bootstrap. This directive uses ng-transclude and handles two types of list items (li) depending on whether it is a dropdown or not. However, I am experiencing issues with the dropdown functio ...

Using TypeScript with Node.js and Sequelize - the process of converting a value to a number and then back to a string within a map function using the OR

Currently, I am facing a challenge in performing addition on currency prices stored as an array of objects. The issue arises from the fact that the currency type can vary among 3 different types within the array of objects. The main hurdle I encounter is ...

The anchorEl state in Material UI Popper is having trouble updating

I am currently facing an issue with the Material UI popper as the anchorEl state remains stuck at null. Although Material UI provides an example using a functional component, I am working with a class-based component where the logic is quite similar. I w ...

Exploring the functions of `map` and `filter` in the world of

Consider this input: var m = [{ name: 'foo', routes: [{verb: 'post', path: '/foo1'}, {verb: 'get', path: '/foo2'}] }, { name: 'bar', routes: [{verb: 'put', path: ...

Ascending Order of WordPress Locations

I need help sorting the order of locations in Word Press, where the locations are stored within the posts meta data. On my home page, there is a drop-down box for users to select a location, and I would like them to be ordered from A - Z <?php ...

Struggling with implementing nested for loops

I am struggling to find a solution for this issue. I need to compare the content of two arrays with each other. If they are exactly the same, I want to execute the if statement; otherwise, I want the else statement to be executed. The current setup is ca ...

Enhancing VueJS2 components by optimizing code structure to eliminate duplicate elements

The following code is used in two different components, so please avoid using props. Utilize data variables and largely similar methods but with different component templates. <template> </template> <script> export default { name ...

Error: "$$" not defined in this context

I am currently working on generating a dynamic pie chart programmatically with the intention of transforming it into a reusable React Component. The main idea is to have an interactive pie chart where each slice expands into a full pie when clicked. I came ...