Releases: radashi-org/radashi
v12.2.0 – Radashi's first stable release
Starting today, you can install radashi@12.2.0 from NPM. This is the first stable release of Radashi, which we've been incubating for more than 4 months, starting on June 23.
Now, we look forward to merging more pull requests, attracting more users, and inspiring more talented folks to join us in building (and just as important, maintaining) the next-generation utility toolkit that is Radashi.
Lastly, I'd like to ask everyone to check out the proposed features open for discussion, and we hope you'll share with us any ideas you may have as well. Remember, this is a community effort. Your perspective is valuable and it will help us make Radashi better with your needs in mind.
New Functions
Add cloneDeep function → PR #81
The cloneDeep function creates a deep copy of an object or array.
- It supports cloning of plain objects, arrays,
Mapinstances, andSetinstances by default. - The default behavior can be customized by providing a partial
CloningStrategyimplementation.
import * as _ from 'radashi'
const obj = { a: 1, b: { c: 2 } }
const clone = _.cloneDeep(obj)
// The clone and its nested objects have their own identity. Therefore,
// mutating them won't affect the original object, and vice versa.
assert(clone !== obj)
assert(clone.b !== obj.b)
assert(JSON.stringify(clone) === JSON.stringify(obj))Add once function → PR #80
Create a wrapper around a given function such that it executes at most once.
- Subsequent calls to the wrapped function return the result from the first execution, regardless of the arguments provided. This behavior is akin to “memoization” but specifically designed for single-use functions.
- Use
_.once.reset(fn)to clear the stored result and allow the function to execute again.
import * as _ from 'radashi'
const fn = _.once(() => Math.random())
fn() // 0.5
fn() // 0.5
_.once.reset(fn)
fn() // 0.8Cast a non-nullish value into an array → PR #97
The castArrayIfExists function ensures that a non-nullish input value is always returned as an array.
- If the input is already an array, it returns a shallow copy of the array.
- If the input is not an array, it wraps the input in a new array.
- Nullish values (null or undefined) are passed through as is.
import * as _ from 'radashi'
_.castArrayIfExists(1) // => [1]
_.castArrayIfExists([1, 2, 3]) // => [1, 2, 3]
_.castArrayIfExists('hello') // => ['hello']
_.castArrayIfExists(null) // => null
_.castArrayIfExists(undefined) // => undefinedCast a value into an array → PR #97
The castArray function ensures that the input value is always returned as an array.
- If the input is already an array, it returns a shallow copy of the array.
- If the input is not an array, it wraps the input in a new array.
import * as _ from 'radashi'
_.castArray(1) // => [1]
_.castArray([1, 2, 3]) // => [1, 2, 3]
_.castArray('hello') // => ['hello']Convert an array to a map → PR #58
The mapify function allows you to convert an array into a Map object, where the keys and values are determined by provided functions.
- The first callback determines the keys of the map.
- The second callback determines the values of the map. If not provided, the original array elements are used as values.
import * as _ from 'radashi'
const fish = [
{ name: 'Marlin', weight: 105 },
{ name: 'Bass', weight: 8 },
{ name: 'Trout', weight: 13 },
]
const fishByName = _.mapify(fish, f => f.name)
// => Map(3) {'Marlin' => { name: 'Marlin', weight: 105 }, 'Bass' => { name: 'Bass', weight: 8 }, 'Trout' => { name: 'Trout', weight: 13 }}
const fishWeightByName = _.mapify(
fish,
f => f.name,
f => f.weight,
)
// => Map(3) { 'Marlin' => 105, 'Bass' => 8, 'Trout' => 13 }Round a number to a specified precision → PR #53
The round function allows you to round a number to a specified precision.
- The precision can be a positive or negative integer.
- An optional rounding function (e.g.
Math.floororMath.ceil) can be provided. The default rounding function isMath.round.
import * as _ from 'radashi'
_.round(123.456) // => 123
_.round(1234.56, -2) // => 1200
_.round(4.001, 2, Math.ceil) // => 4.01
_.round(4.089, 2, Math.floor) // => 4.08Allow deep traversal of objects and arrays → PR #59
The traverse function recursively visits each property of an object (or each element of an array) and its nested objects or arrays.
- By default, the only nested objects to be traversed are plain objects and arrays.
- Traversal is performed in a depth-first manner, and circular references are skipped.
- The traversal can be customized with a
TraverseOptionsobject.
import * as _ from 'radashi'
const root = { a: { b: 2 }, c: [1, 2] }
_.traverse(root, (value, key, parent, context) => {
const indent = ' '.repeat(context.parents.length)
console.log(`${indent}${key} => ${value}`)
})
// Logs the following:
// a => { b: 2 }
// b => 2
// c => [1, 2]
// 0 => 1
// 1 => 2Calculate string similarity → PR #122
The similarity function calculates the Levenshtein distance between two input strings, which represents the minimum number of single-character edits (insertions, deletions, or substitutions) required to change one string into the other.
- A lower number indicates higher similarity, with 0 meaning the strings are identical.
- The comparison is both case-sensitive and whitespace-significant.
- The argument order doesn't matter, as it's symmetric.
import * as _ from 'radashi'
// Identical strings
_.similarity('hello', 'hello') // => 0
// One character difference
_.similarity('kitten', 'sitten') // => 1
// Multiple differences
_.similarity('saturday', 'sunday') // => 3Cast a value into a comparator function → PR #34
The castComparator function allows you to create a comparator function that can be passed into Array.prototype.sort.
Parameters:
mappingis either a property name or a mapping function.compareis an optional custom compare function (e.g. forlocaleCompareuse cases).reversereverses the comparison order if set totrue.
import * as _ from 'radashi'
const users = [
{ id: 1, firstName: 'Alice', lastName: 'Smith' },
{ id: 3, firstName: 'Charlie', lastName: 'Brown' },
{ id: 2, firstName: 'Drew', lastName: 'Johnson' },
]
const compareById = _.castComparator('id')
users.sort(compareById)
// [Alice, Drew, Charlie]
const compareByFullName = _.castComparator(
user => `${user.firstName} ${user.lastName}`,
(a, b) => b.localeCompare(a),
)
users.sort(compareByFullName)
// [Alice, Charlie, Drew]
const compareByFullNameReversed = _.castComparator(
user => `${user.firstName} ${user.lastName}`,
(a, b) => b.localeCompare(a),
true,
)
users.sort(compareByFullNameReversed)
// [Drew, Charlie, Alice]