Skip to content
VersionSize

seek

The seek utility performs a deep fuzzy search within an object or array. It recursively scans all properties and values to determine if any of them match the search query based on a similarity threshold (tone).

Source Code

View Source Code
ts
import { assert } from '../function/assert';
import { similarity } from '../string/similarity';
import { isArray } from '../typed/isArray';
import { isNil } from '../typed/isNil';
import { isNumber } from '../typed/isNumber';
import { isObject } from '../typed/isObject';
import { isString } from '../typed/isString';
import { IS_WITHIN_ERROR_MSG, isWithin } from '../typed/isWithin';

/**
 * Recursively checks if an object contains a value similar to the search string.
 *
 * @example
 * ```ts
 * const obj = { a: 'hello', b: { c: 'world' }, d: [1, 2, 3] };
 *
 * seek(obj, 'hello'); // true
 * seek(obj, 'world'); // true
 * seek(obj, 'foo'); // false
 * seek(obj, 'hello', 0.5); // true
 * seek(obj, 'hello', 0.8); // true
 * seek(obj, 'hello', 1); // true
 * seek(obj, 'hello', 1.5); // false
 * seek(obj, 'hello', -1); // false
 * seek(obj, 'hello', 0); // false
 * ```
 *
 * @param item - The object to search within.
 * @param query - The search string.
 * @param [tone=1] - The similarity threshold.
 *
 * @returns Whether the object contains a matching value.
 */
function _seek<T>(item: T, query: string, tone: number): boolean {
  if (isNil(item)) return false;

  if (isString(item) || isNumber(item)) {
    return similarity(String(item), query) >= tone;
  }

  if (isArray(item)) {
    return (item as unknown[]).some((value) => _seek(value, query, tone));
  }

  if (isObject(item)) {
    return Object.values(item as Record<string, unknown>).some((value) =>
      isNil(value) ? false : _seek(value, query, tone),
    );
  }

  return false;
}

export function seek<T>(item: T, query: string, tone = 1): boolean {
  assert(isWithin(tone, 0, 1), IS_WITHIN_ERROR_MSG, { args: { max: 1, min: 0, tone }, type: TypeError });

  return _seek(item, query, tone);
}

Features

  • Isomorphic: Works in both Browser and Node.js.
  • Deep Scanning: Recursively searches through nested objects and arrays.
  • Fuzzy Matching: Matches values even with partial strings or slight variations.
  • Configurable Sensitivity: Adjust the "tone" to control how strict or loose the matching should be.

API

ts
function seek<T>(item: T, query: string, tone?: number): boolean;

Parameters

  • item: The object, array, or value to search within.
  • query: The search string (case-insensitive).
  • tone: Optional. A similarity threshold between 0 and 1 (defaults to 1 for exact-like matching).

Returns

  • true if a matching value is found anywhere within the structure; otherwise, false.

Examples

Deep Value Searching

ts
import { seek } from '@vielzeug/toolkit';

const data = {
  id: 1,
  meta: {
    title: 'Hello World',
    author: { name: 'Alice' },
  },
  tags: ['coding', 'typescript'],
};

seek(data, 'hello'); // true (matches title)
seek(data, 'alice'); // true (matches nested author name)
seek(data, 'type'); // true (matches tag)
seek(data, 'missing'); // false

Using Similarity (Tone)

ts
import { seek } from '@vielzeug/toolkit';

const item = { label: 'Vielzeug Toolkit' };

// Loose match
seek(item, 'viel', 0.5); // true

// Strict match
seek(item, 'viel', 1.0); // false

Implementation Notes

  • Throws TypeError if tone is not between 0 and 1.
  • Scans all enumerable properties and values.
  • Case-insensitive comparison is used for string values.
  • Internally leverages the similarity utility.

See Also

  • get: Safely retrieve a value at a specific known path.
  • similarity: The underlying string comparison helper.
  • isEqual: Check for exact deep equality.