diff --git a/files/index.d.ts b/files/index.d.ts index eb44d2f0..26c8254e 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -6106,6 +6106,25 @@ Notes: export function pathSatisfies(pred: (val: T) => boolean, path: Path): (obj: U) => boolean; export function pathSatisfies(pred: (val: T) => boolean, path: Path, obj: U): boolean; +/* +Method: swap + +Explanation: + +Example: + +``` +``` + +Categories: + +Notes: + +*/ +// @SINGLE_MARKER +export function swap(indexA: number, indexB: number): (list: T[]) => T[]; +export function swap(indexA: number, indexB: number, list: T[]): T[]; + // RAMBDAX_MARKER_START /* diff --git a/source/swap.js b/source/swap.js new file mode 100644 index 00000000..3a0e8be5 --- /dev/null +++ b/source/swap.js @@ -0,0 +1,42 @@ +import { isArray } from './_internals/isArray.js'; +import { curry } from './curry.js'; + +export function swapArrayOrString(indexA, indexB, iterable) { + const actualIndexA = indexA < 0 ? iterable.length + indexA : indexA; + const actualIndexB = indexB < 0 ? iterable.length + indexB : indexB; + if ( + actualIndexA === actualIndexB || + Math.min(actualIndexA, actualIndexB) < 0 || + Math.max(actualIndexA, actualIndexB) >= iterable.length + ) + return iterable; + if (typeof iterable === 'string') { + return ( + iterable.slice(0, actualIndexA) + + iterable[actualIndexB] + + iterable.slice(actualIndexA + 1, actualIndexB) + + iterable[actualIndexA] + + iterable.slice(actualIndexB + 1) + ); + } + const clone = iterable.slice(); + const temp = clone[actualIndexA]; + clone[actualIndexA] = clone[actualIndexB]; + clone[actualIndexB] = temp; + return clone; +} +export function swapFn(indexA, indexB, iterable) { + if (isArray(iterable) || typeof iterable === 'string') + return swapArrayOrString(indexA, indexB, iterable); + + const aVal = iterable[indexA]; + const bVal = iterable[indexB]; + if (aVal === undefined || bVal === undefined) return iterable; + return { + ...iterable, + [indexA]: iterable[indexB], + [indexB]: iterable[indexA], + }; +} + +export const swap = curry(swapFn); diff --git a/source/swap.spec.js b/source/swap.spec.js new file mode 100644 index 00000000..2085bb54 --- /dev/null +++ b/source/swap.spec.js @@ -0,0 +1,40 @@ +import { swap } from './swap'; +const list = ['a', 'b', 'c', 'd', 'e', 'f']; + +it('swaps an element from one index to the other', () => { + expect(swap(0, 1, list)).toEqual(['b', 'a', 'c', 'd', 'e', 'f']); + expect(swap(2, 1, list)).toEqual(['a', 'c', 'b', 'd', 'e', 'f']); + expect(swap(-1, 0, list)).toEqual(['f', 'b', 'c', 'd', 'e', 'a']); + expect(swap(4, 1, list)).toEqual(['a', 'e', 'c', 'd', 'b', 'f']); +}); + +it('does nothing when indexes are outside the list boundaries', () => { + expect(swap(-20, 2, list)).toEqual(list); + expect(swap(20, 2, list)).toEqual(list); + expect(swap(2, 20, list)).toEqual(list); + expect(swap(2, -20, list)).toEqual(list); + expect(swap(20, 20, list)).toEqual(list); + expect(swap(-20, -20, list)).toEqual(list); +}); + +it('does nothing when indexes are equal', () => { + expect(swap(0, 0, list)).toEqual(list); +}); + +it('should be the same when swapping index order', () => { + expect(swap(0, 1, list)).toEqual(swap(1, 0, list)); +}); + +it('swaps property values from one property to another', () => { + expect(swap('a', 'b', { a: 1, b: 2 })).toEqual({ a: 2, b: 1 }); + expect(swap('b', 'a', { a: 1, b: 2 })).toEqual({ a: 2, b: 1 }); +}); + +it('does nothing when property names are not defined', () => { + expect(swap('a', 'b', { a: 1 })).toEqual({ a: 1 }); + expect(swap('a', 'b', { b: 2 })).toEqual({ b: 2 }); +}); + +it('swaps characters in string from one index to another', () => { + expect(swap(0, 2, 'foo')).toEqual('oof'); +});