-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new-log-viewer: Add bounds checking and search methods to support log filtering around a specific log event. #81
Changes from 2 commits
e07805b
8cbe208
0e8b80d
da3f4ad
0cc5234
55ce5bd
71a5626
b3f890f
a18d4c0
5997721
f9eb7f8
9507607
6f33822
6794146
f95d90d
7ba6706
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import {Nullable} from "../typings/common"; | ||
|
||
|
||
/** | ||
* Performs binary search to find the smallest index `i` in the range [0, n) where the | ||
* `conditionFn` is true. Assumes that the `conditionFn` is false for some prefix of the | ||
* input range and true for the remainder. The most common use is find the index `i` of | ||
* a value x in a sorted array. | ||
* | ||
* @param n The length of the range to search. | ||
* @param conditionFn A function that takes an index and returns `true` or `false`. | ||
* @return The smallest index where `conditionFn(i)` is true. If no such index exists, returns `n`. | ||
* @example | ||
* const arr = [1, 3, 5, 7, 10, 15, 20]; | ||
* const result = binarySearch(arr.length, (i) => arr[i] >= 10); | ||
* console.log(result); // Output: 4 (since arr[4] is 10). | ||
*/ | ||
const binarySearch = (n: number, conditionFn: (index: number) => boolean): number => { | ||
// Generic implementation based on Go standard library implementation. | ||
// Reference: https://pkg.go.dev/sort#Search | ||
let i = 0; | ||
let j = n; | ||
|
||
while (i < j) { | ||
const mid = Math.floor((i + j) / 2); | ||
|
||
if (false === conditionFn(mid)) { | ||
i = mid + 1; | ||
} else { | ||
j = mid; | ||
} | ||
} | ||
|
||
return i; | ||
}; | ||
|
||
/** | ||
* Finds the largest index `i` in a sorted array `data` such that `data[i] <= x`. | ||
* Uses binary search for efficiency. Returns 0 if `x` is less than `data[0]`. | ||
* | ||
* @param data Sorted array. | ||
* @param x Target value. | ||
* @return The largest index where `data[i] <= x`. There are 2 edge cases where returns: | ||
* - 0 if `x` is less than `data[0]`. | ||
* - `null` if array is empty. | ||
* @example | ||
* const arr = [2, 3, 5, 7, 10, 15, 20]; | ||
* const result = findLargestIdxLte(arr, 8); | ||
* console.log(result); // Output: 3 (since arr[3] is 7). | ||
*/ | ||
const findLargestIdxLte = (data: number[], x: number): Nullable<number> => { | ||
const {length} = data; | ||
|
||
if (0 === n) { | ||
return null; | ||
} | ||
|
||
// Binary search to find the first index where data[i] > x. | ||
const firstGreaterIdx: number = binarySearch(n, (i) => data[i] as number > x); | ||
|
||
if (0 === firstGreaterIdx) { | ||
return 0; | ||
} | ||
davemarco marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return firstGreaterIdx - 1; | ||
}; | ||
davemarco marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* Finds the largest index `i` in a sorted array `data` such that `data[i] <= x`. | ||
* Uses binary search for efficiency. This method is strict in that it | ||
* returns `null` if `x` is less than `data[0]` or greater than `data[n-1]`. | ||
* i.e. it informs the caller if x is outside the bounds of `data`. | ||
* | ||
* @param data Sorted array. | ||
* @param x Target value. | ||
* @return The largest index where `data[i] <= x`. Returns `null` in the following cases: | ||
* - `x` is less than `data[0]`. | ||
* - `x` is greater than `data[n-1]`. | ||
* - The array is empty. | ||
* @example | ||
* const arr = [2, 3, 5, 7, 10, 15, 20]; | ||
* const result = strictFindLargestIdxLte(arr, 8); | ||
* console.log(result); // Output: 3 (since arr[3] is 7). | ||
*/ | ||
const strictFindLargestIdxLte = (data: number[], x: number): Nullable<number> => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried reading the PR description but can't understand the purpose of this function. Would you mind helping me to understand it a bit? Say we are performing binary search in an array, it's with the assumption that the numbers are strictly incremental. If we want to make sure the desired number There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure that might make more sense lol. I added a new function |
||
const n = data.length; | ||
|
||
if (0 === n) { | ||
return null; | ||
} | ||
|
||
// Binary search to find the first index where data[i] > x. | ||
const firstGreaterIdx: number = binarySearch(n, (i) => data[i] as number > x); | ||
|
||
if (0 === firstGreaterIdx) { | ||
return null; | ||
} | ||
|
||
const valueAtLastIndex: number = data[n - 1] as number; | ||
if (firstGreaterIdx === n && valueAtLastIndex !== x) { | ||
// Return null if x is greater than the highest value in the array. | ||
return null; | ||
davemarco marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return firstGreaterIdx - 1; | ||
}; | ||
davemarco marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export { | ||
findLargestIdxLte, | ||
strictFindLargestIdxLte, | ||
}; | ||
davemarco marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: shall we place those util functions into
utils/data.ts
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure i'll move them