|
| 1 | +--- |
| 2 | +title: Binary Search |
| 3 | +description: A hook for implementing binary search. |
| 4 | +component: true |
| 5 | +--- |
| 6 | + |
| 7 | +## About |
| 8 | + |
| 9 | +The `useBinarySearch` hook is a custom React hook that provides a binary search algorithm implementation. It supports searching in a sorted array of primitive values or complex objects, with an option to define custom comparison logic. The hook handles various edge cases, such as empty arrays, unsorted arrays, and invalid inputs, ensuring robustness in production. |
| 10 | + |
| 11 | +## Parameters |
| 12 | + |
| 13 | +| Name | Type | Description | |
| 14 | +| ---------- | --------------------------------- | ------------------------------------------------------------------------------------------------------- | |
| 15 | +| array | `T[]` | The sorted array in which to perform the search. This parameter is required when calling `startSearch`. | |
| 16 | +| target | `T` | The target value to search for in the array. | |
| 17 | +| comparator | `(a: T, b: T) => number` | Optional. Custom comparison function for sorting complex data types (objects). | |
| 18 | +| onComplete | `(index: number or null) => void` | Optional. Callback function that gets called after searching completes. | |
| 19 | + |
| 20 | +## Return Values |
| 21 | + |
| 22 | +| Name | Type | Description | |
| 23 | +| ----------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | |
| 24 | +| foundIndex | `number` or `null` | The sorted array after the sorting process completes. | |
| 25 | +| isSearching | `boolean` | A boolean indicating if the search is currently in progress. | |
| 26 | +| startSearch | `(array: T[], target: T, comparator?: (a: T, b: T) => number, onComplete?: (index: number or null) => void) => void` | A function that initiates the binary search process on the given array. | |
| 27 | +| reset | `() => void` | A function to reset the hook's state, clearing the search result and resetting the search status. | |
| 28 | + |
| 29 | +## Installation |
| 30 | + |
| 31 | +<Tabs defaultValue="cli"> |
| 32 | + |
| 33 | +<TabsList> |
| 34 | + <TabsTrigger value="cli">CLI</TabsTrigger> |
| 35 | + <TabsTrigger value="manual">Manual</TabsTrigger> |
| 36 | +</TabsList> |
| 37 | + |
| 38 | +<TabsContent value="cli"> |
| 39 | + |
| 40 | +<Steps> |
| 41 | + |
| 42 | +<Step>Run the following command:</Step> |
| 43 | + |
| 44 | +```bash |
| 45 | +npx scriptkavi-hooks@latest add binary-search |
| 46 | +``` |
| 47 | + |
| 48 | +</Steps> |
| 49 | + |
| 50 | +</TabsContent> |
| 51 | + |
| 52 | +<TabsContent value="manual"> |
| 53 | + |
| 54 | +<Steps> |
| 55 | + |
| 56 | +<Step>Copy and paste the following code into your project.</Step> |
| 57 | + |
| 58 | +<ComponentSource name="binary-search" /> |
| 59 | + |
| 60 | +<Step>Update the import paths to match your project setup.</Step> |
| 61 | + |
| 62 | +</Steps> |
| 63 | + |
| 64 | +</TabsContent> |
| 65 | + |
| 66 | +</Tabs> |
| 67 | + |
| 68 | +## Usage |
| 69 | + |
| 70 | +```tsx |
| 71 | +import { useBinarySearch } from "@/hooks/binary-search" |
| 72 | +``` |
| 73 | + |
| 74 | +### Basic |
| 75 | + |
| 76 | +```tsx |
| 77 | +import React, { useState } from "react" |
| 78 | + |
| 79 | +function BinarySearchComponent() { |
| 80 | + const [array, setArray] = useState<number[]>([1, 3, 5, 7, 9, 11, 13, 15]) |
| 81 | + const { foundIndex, isSearching, startSearch, reset } = |
| 82 | + useBinarySearch<number>() |
| 83 | + |
| 84 | + return ( |
| 85 | + <div> |
| 86 | + <h3>Array: {array.join(", ")}</h3> |
| 87 | + <h3>Found Index: {foundIndex !== null ? foundIndex : "Not Found"}</h3> |
| 88 | + |
| 89 | + <button onClick={() => startSearch(array, 7)} disabled={isSearching}> |
| 90 | + {isSearching ? "Searching..." : "Search for 7"} |
| 91 | + </button> |
| 92 | + |
| 93 | + <button onClick={reset} disabled={isSearching}> |
| 94 | + Reset |
| 95 | + </button> |
| 96 | + </div> |
| 97 | + ) |
| 98 | +} |
| 99 | + |
| 100 | +export default BinarySearchComponent |
| 101 | +``` |
| 102 | + |
| 103 | +### Binary Search with Custom Comparator |
| 104 | + |
| 105 | +You can search through an array of objects by providing a custom comparator function. Here is an example where we search for an object in an array based on a property (e.g. `age`). |
| 106 | + |
| 107 | +```tsx |
| 108 | +import React, { useState } from "react" |
| 109 | + |
| 110 | +type Person = { |
| 111 | + name: string |
| 112 | + age: number |
| 113 | +} |
| 114 | + |
| 115 | +function ObjectBinarySearchComponent() { |
| 116 | + const [people] = useState<Person[]>([ |
| 117 | + { name: "Alice", age: 25 }, |
| 118 | + { name: "Bob", age: 30 }, |
| 119 | + { name: "Charlie", age: 35 }, |
| 120 | + { name: "David", age: 40 }, |
| 121 | + ]) |
| 122 | + |
| 123 | + const { foundIndex, isSearching, startSearch, reset } = |
| 124 | + useBinarySearch<Person>() |
| 125 | + |
| 126 | + const compareByAge = (a: Person, b: Person) => a.age - b.age |
| 127 | + |
| 128 | + return ( |
| 129 | + <div> |
| 130 | + <h3>People:</h3> |
| 131 | + <ul> |
| 132 | + {people.map((person) => ( |
| 133 | + <li key={person.name}> |
| 134 | + {person.name} - {person.age} years old |
| 135 | + </li> |
| 136 | + ))} |
| 137 | + </ul> |
| 138 | + |
| 139 | + <h3>Found Index: {foundIndex !== null ? foundIndex : "Not Found"}</h3> |
| 140 | + |
| 141 | + <button |
| 142 | + onClick={() => startSearch(people, { name: "", age: 35 }, compareByAge)} |
| 143 | + disabled={isSearching} |
| 144 | + > |
| 145 | + {isSearching ? "Searching..." : "Search for age 35"} |
| 146 | + </button> |
| 147 | + |
| 148 | + <button onClick={reset} disabled={isSearching}> |
| 149 | + Reset |
| 150 | + </button> |
| 151 | + </div> |
| 152 | + ) |
| 153 | +} |
| 154 | + |
| 155 | +export default ObjectBinarySearchComponent |
| 156 | +``` |
| 157 | + |
| 158 | +### Completion Callback |
| 159 | + |
| 160 | +You can also pass a callback function that will be triggered when the search is complete, allowing you to execute additional logic after the search finishes. |
| 161 | + |
| 162 | +```tsx |
| 163 | +import React from "react" |
| 164 | + |
| 165 | +const CompletionCallbackComponent = () => { |
| 166 | + const array = [2, 4, 6, 8, 10, 12, 14] |
| 167 | + const { startSearch, foundIndex, isSearching } = useBinarySearch<number>() |
| 168 | + |
| 169 | + return ( |
| 170 | + <div> |
| 171 | + <h3>Array: {array.join(", ")}</h3> |
| 172 | + <h3>Found Index: {foundIndex !== null ? foundIndex : "Not Found"}</h3> |
| 173 | + |
| 174 | + <button |
| 175 | + onClick={() => |
| 176 | + startSearch(array, 10, undefined, (index) => { |
| 177 | + console.log("Search completed. Index found:", index) |
| 178 | + }) |
| 179 | + } |
| 180 | + disabled={isSearching} |
| 181 | + > |
| 182 | + {isSearching ? "Searching..." : "Search for 10"} |
| 183 | + </button> |
| 184 | + </div> |
| 185 | + ) |
| 186 | +} |
| 187 | + |
| 188 | +export default CompletionCallbackComponent |
| 189 | +``` |
| 190 | + |
| 191 | +### Custom Comparator Example |
| 192 | + |
| 193 | +You can use a custom comparator function to search through arrays of objects or other complex data types. The comparator should return: |
| 194 | + |
| 195 | +```tsx |
| 196 | +const compareByAge = (a: Person, b: Person) => a.age - b.age |
| 197 | +``` |
| 198 | + |
| 199 | +You can pass this comparator function as the second argument to `startSearch` to search the array based on a custom logic. |
| 200 | + |
| 201 | +### Considerations |
| 202 | + |
| 203 | +- Array Must Be Sorted: Ensure that the input array is sorted based on the |
| 204 | + same criteria used by the comparator function for accurate results. |
| 205 | + |
| 206 | +- Edge Cases: The hook handles cases like empty arrays, arrays with one |
| 207 | + element, and invalid inputs. |
| 208 | + |
| 209 | +- Asynchronous Search: You can introduce asynchronous behavior (e.g., |
| 210 | + setTimeout or requestIdleCallback) to prevent blocking the UI during long |
| 211 | + searches. |
0 commit comments