Is it possible to perform a binary search on a collection of objects in an array?

As I delve into the world of searching and sorting algorithms, I've encountered a challenge with implementing a binary search on an array of customer objects. This particular array is sorted by both first and last name.

The objective here is to locate a customer's email address within the data set and retrieve its corresponding index.

A snippet of the data structure is shown below:

[
  {
    "username": "Maude.Torp",
    "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="94c0f5edf5badff1e6f8e1fff1a1a7d4f3f9f5fdf8baf7fbf9">[email protected]</a>",
    "address": {
      "street": "Rowe Fields",
      "suite": "Suite 231",
      "city": "Tiannamouth",
      "zipcode": "07584-6653",
      "geo": { "lat": "75.0283", "lng": "-17.1824" }
    },
    "phone": "795-827-5446 x18366",
    "website": "nico.com",
    "company": {
      "name": "Champlin, Feest and Barrows",
      "catchPhrase": "Object-based user-facing orchestration",
      "bs": "transition integrated content"
    },
    "firstName": "Maida",
    "lastName": "Feeney"
  },
  ...
]

The current implementation of my binary search function is as follows:

function searchByEmail(email, customers) {
  let start = 0;
  let end = customers.length - 1;

  while (start <= end) {
    let middle = Math.floor((start + end) / 2);

    if (customers[middle] === email) {
      return middle;
    } else if (customers[middle] < email) {
      start = middle + 1;
    } else {
      end = middle - 1;
    }
  }
  return -1;
}

While this function works for sorted arrays of numbers by returning the index of the desired key, it only outputs -1 when applied to arrays of objects like the one described above. Any tips on adjusting this algorithm to accommodate object searches?

Answer №1

To efficiently search the customer array using binary search, make sure it is sorted by customer email.

Modify the code to compare emails instead of the entire object, focusing on the email property within each object.

function findCustomerByEmail(email, customers) {
  let startIndex = 0;
  let endIndex = customers.length - 1;

  while (startIndex <= endIndex) {
    let middleIndex = Math.floor((startIndex + endIndex) / 2);

    // Note the addition of ".email"
    if (customers[middleIndex].email === email) {
      return middleIndex;
    } else if (customers[middleIndex].email < email) {
      startIndex = middleIndex + 1;
    } else {
      endIndex = middleIndex - 1;
    }
  }
  return -1;
}

Answer №2

You have the option to integrate a binary search method into Array.prototype, enabling you to utilize it as equivalents to lower_bound or upper_bound in C++. This custom array prototype method will determine and return the closest index of an element within the array.

Below is my personalized implementation:

Array.prototype.binarySearch = function(target, compare = (a, b) => a < b) {
  let left = 0;
  let right = this.length;

  while (left != right - 1) {
    const mid = Math.floor((left + right) / 2);
    if (compare(this[mid], target)) {
      left = mid;
    } else {
      right = mid;
    }
  }

  return left + compare(this[left], target);
};

// array sorted by age
const arr = [
  { age: 10, name: 'nick'},
  { age: 20, name: 'john'},
  { age: 30, name: 'aaron'},
  { age: 30, name: 'ana'},
  { age: 30, name: 'ana'},
  { age: 30, name: 'casandra'},
  { age: 40, name: 'dave'}, 
  { age: 40, name: 'jake'},
  { age: 50, name: 'pablo'}
];

// searching based on age

const lowByAge = arr.binarySearch({ age: 30 }, (a, b) => a.age < b.age);
console.log('lower_bound (age):', lowByAge); // lower_bound (age): 2

const upByAge = arr.binarySearch({ age: 30 }, (a, b) => a.age <= b.age);
console.log('upper_bound (age):', upByAge); // upper_bound (age): 6

// searching based on age and name

const lowByAgeAndName = arr.binarySearch({ age: 30, name: 'ana' }, (a, b) => 
    (a.age == b.age) ?  a.name < b.name : a.age < b.age);
console.log('lower_bound (age, name):', lowByAgeAndName); // lower_bound (age, name): 3

const upByAgeAndName = arr.binarySearch({ age: 30, name: 'ana' }, (a, b) => 
    (a.age == b.age) ?  a.name <= b.name : a.age < b.age);
console.log('upper_bound (age, name):', upByAgeAndName); // upper_bound (age, name): 5

Now you can incorporate this method in any function of your choice.

Answer №3

Expanding on the previous responses,

A sorted array of objects can indeed be subjected to binary search. However, this method is less efficient when dealing with unsorted arrays.

In the case of an unsorted array, two steps are required:

  1. The array must be sorted first (O(n) complexity)
  2. Then implement binary search (O(n) complexity)

The total complexity of these steps combined is O(n*n).

Alternatively, for an unsorted array, linear search is more suitable with a complexity of O(n).

When handling an array of objects that is already sorted, the process involves accessing and comparing values within each object instead of directly comparing values in the array elements. The core algorithm remains similar to binary search.

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

Using an array to substitute a string in JavaScript

xyz1 xyz2 xyz3 xyz4 xyz5 xyz6 xyz7 xyz8 xyz9 Given the CSV above, transform the sentence below by removing the double quotes and replacing them with the corresponding values from the CSV: "" is going with "" to "" for something to know. ...

Accessing struct array members is not possible by using pointer index

Attempting to retrieve data from a global array of structures, I encounter a crash within the application. #include <stdio.h> typedef struct { char *fruit; int score; } t_fruitdata; static t_fruitdata fruittable[] = { {"Apple", 100}, ...

The DataTable is encountering difficulties with processing JSON data retrieved from the database

Setting up a datatable on my website has been quite the challenge. I came across a table that I wanted to use here, but converting it to fit my needs has not been successful. Currently, the table is not populating with rows from a database table and I&apos ...

How can I cancel or reset a timeInterval in AngularJS?

In my project demo, I have implemented a feature that fetches data from the server at regular intervals using $interval. Now, I am looking for a way to stop or cancel this process. Can you guide me on how to achieve this? And if I need to restart the proce ...

Increase the value of $index within the ng-repeat loop

Is there a way to increment the value of $index in ng-repeat by a specific amount? For example, if I want to display two values at a time, how can I ensure that the next iteration starts with the third value instead of the second value? <div ng-contr ...

Is there a way to selectively update specific keys within existing objects in Mongodb without affecting the rest of the

Here is the scenario I am dealing with: Within my Angular 8 application, I am responsible for creating and managing invoices. The structure of an invoice object looks like this: { "_id": { "$oid": "5ea9ad58f65d8d49841362bd" }, "details": [ { ...

What advantages do interfaces as data types offer in Angular compared to using classes?

After watching a tutorial from my teacher, he showed us this code snippet: https://i.sstatic.net/MA3Z9.png He mentioned that the products array, defined as type any [], is not taking advantage of TypeScript's strongly typing. He suggested using an I ...

Is it possible to use Node.js child processes without carriage returns?

My Node.js script is set up to handle some database operations by creating child processes using the spawn functionality. However, I encountered a strange issue where the output stopped displaying carriage returns. Here's an example of what was happen ...

How to update a dynamic list or array in Flutter using setState()?

Although I'm still new to flutter and struggling a bit with understanding state management compared to React, I've encountered some challenges in handling array variables. When attempting to setState with a different approach, I end up with unexp ...

The struggle of encoding: Making a JSON ajax call (utf-8) to convert Latin1 characters to uppercase

I've encountered a particular issue: the Javascript library I am developing utilizes JSON cross-domain requests to fetch data from a backend powered by Ruby on Rails: function getData() { $.ajaxSetup({ 'beforeSend': function(xhr) {xhr.s ...

Firebase causing API to render only upon typing initiation

I have been working on developing a Twitter-like app using React and Firebase, but I have come across a small bug. Currently, I am using useEffect to display my firebase collection when the page loads, and then mapping the tweets to the page. However, the ...

Updating the values of parent components in Vue.js 3 has been discovered to not function properly with composite API

Here is a Vue component I have created using PrimeVue: <template lang="pug"> Dialog(:visible="dShow" :modal="true" :draggable="false" header="My Dialog" :style="{ width: '50vw' }" ...

Building routes for a stationary website with Angular

Currently, I am in the process of developing a static site using a combination of HTML, CSS, and JS along with nodeJS and express for server-side functionality... One challenge I am facing is setting up routes to display pages like /about instead of acces ...

retrieving data from array elements

{ "success": true, "users": [ { "photo": { "id": "users/m1ul7palf4iqelyfhvyv", "secure_url": "https://res.cloudinary.com/dpbdw6lxh/image/upload/v1665251810 ...

Request to api.upcitemdb.com endpoint encountering CORS issue

This code may seem simple, but for some reason, it's not working as expected. What I'm trying to achieve is to call the GET API at: I want to make this API call using either JavaScript or jQuery. I've attempted various approaches, but none ...

Placing a freshly created item into a designated array while ensuring it is positioned at Index Value [0] rather than at [arr.length-1]

I understand that it is usually recommended to add new objects at the end of an existing array without a name. However, I am interested in exploring a more complex scenario in order to learn. Specifically, I would like to add a new object at index [0] inst ...

Ensure that the link's color remains constant and remove any styling of text-decoration

Attempting to create a customized header. My goal is to change the color and remove text decoration in the navbar. Below is my code snippet: ReactJS: import React from 'react'; import './Header.css'; function Header() { return ( ...

Discovering complimentary number sequences amidst intersecting number sequences

I have a specific number of arrays, each containing a set amount of elements. Each element consists of two attributes represented by numbers. { start: x end: y } These start and end numbers define a range, where the start value is always smaller tha ...

Object-oriented programming in JavaScript allows for the passing of variables to a parent class using $

I am attempting to transfer variables from an XML file to the parent class in JavaScript. The code follows Object-Oriented Programming principles, with a class named "example" and a method called getData(). The issue I'm encountering is that the AJAX ...

Error encountered when auto-generating IDs in Next.js with Firebase Firestore database

Hello, I am trying to access the details of my page in Next.js and retrieve data from a Firestore database. Here is the error message I am encountering: Firebase initialized successfully page.js:32 router.query: undefined page.js:34 Movie ID: undefined p ...