alternate
The alternate utility toggles an item's presence in an array. If the item exists (based on a value or a custom selector), it is removed. If it doesn't exist, it is added to the array using a specified strategy.
Implementation
View Source Code
ts
import type { Primitive } from '../types';
/**
* Either adds or removes an item from an array, based on whether it already exists in the array.
*
* @example
* ```ts
* alternate([1, 2, 3], 4) // [1, 2, 3, 4]
* alternate([1, 2, 3], 2) // [1, 3]
*
* alternate(
* [{ id: 1 }, { id: 2 }],
* { id: 3 },
* (obj) => obj.id,
* { strategy: 'prepend' }
* ) // [{ id: 3 }, { id: 1 }, { id: 2 }]
* ```
*
* @param array - The array to modify.
* @param item - The item to add or remove.
* @param selector - A function to determine the uniqueness of the item.
* @param [options] - Options for the alternate operation.
* @param [options.strategy] - The strategy to use when adding the item ('prepend' or 'append').
*
* @returns A new array with the item added or removed.
*/
export function alternate<T>(
array: T[],
item: T,
selector?: (item: T) => Primitive,
options: { strategy?: 'prepend' | 'append' } = {},
): T[] {
const { strategy = 'append' } = options;
const compareFn = selector ? (el: T) => selector(el) === selector(item) : (el: T) => el === item;
const index = array.findIndex(compareFn);
if (index !== -1) {
return [...array.slice(0, index), ...array.slice(index + 1)];
}
return strategy === 'prepend' ? [item, ...array] : [...array, item];
}
alternate.fp = true;Features
- Isomorphic: Works in both Browser and Node.js.
- Smart Toggling: Automatically handles addition and removal logic.
- Custom Uniqueness: Support for complex objects via a selector function.
- Flexible Positioning: Control where new items are added (prepend or append).
API
ts
function alternate<T>(
array: T[],
item: T,
selector?: (item: T) => Primitive,
options?: { strategy?: 'prepend' | 'append' },
): T[];Parameters
array: The array to modify.item: The item to toggle.selector: Optional. A function that returns a primitive value used to determine uniqueness (defaults to direct comparison).options: Optional configuration:strategy: Where to add the item if it's missing ('prepend' or 'append', defaults to 'append').
Returns
- A new array with the item either added or removed.
Examples
Toggling Primitives
ts
import { alternate } from '@vielzeug/toolkit';
const numbers = [1, 2, 3];
// Add 4
alternate(numbers, 4); // [1, 2, 3, 4]
// Remove 2
alternate(numbers, 2); // [1, 3]Toggling Objects with a Selector
ts
import { alternate } from '@vielzeug/toolkit';
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const newUser = { id: 3, name: 'Charlie' };
const existingUser = { id: 1, name: 'Alice Smith' };
// Toggle based on ID
const result1 = alternate(users, newUser, (u) => u.id);
// [{ id: 1, ... }, { id: 2, ... }, { id: 3, ... }]
const result2 = alternate(users, existingUser, (u) => u.id);
// [{ id: 2, name: 'Bob' }]Using a Custom Strategy
ts
import { alternate } from '@vielzeug/toolkit';
const list = ['B', 'C'];
// Add 'A' to the beginning
alternate(list, 'A', undefined, { strategy: 'prepend' }); // ['A', 'B', 'C']Implementation Notes
- Returns a new array; the original array is never mutated.
- When removing, all instances matching the item (or selector result) are removed.
- Throws
TypeErrorif the first argument is not an array.