A practical functional library for JavaScript programmers.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Ramda provides 94 comprehensive functions for working with arrays and list-like structures. These functions follow Ramda's core principles of immutability, currying, and function-first data-last parameter order.
Transform each element of a list using a function.
/**
* @param {Function} fn - Transformation function (a -> b)
* @param {Array} list - List to transform
* @returns {Array} New list with transformed elements
*/
R.map(fn, list)
// Examples
R.map(x => x * 2, [1, 2, 3, 4]); // => [2, 4, 6, 8]
R.map(R.toUpper, ['hello', 'world']); // => ['HELLO', 'WORLD']
R.map(R.prop('name'), [{name: 'John'}, {name: 'Jane'}]); // => ['John', 'Jane']
// Curried usage
const double = R.map(R.multiply(2));
double([1, 2, 3]); // => [2, 4, 6]Select elements that satisfy a predicate function.
/**
* @param {Function} predicate - Test function (a -> Boolean)
* @param {Array} list - List to filter
* @returns {Array} New list with matching elements
*/
R.filter(predicate, list)
// Examples
R.filter(x => x > 5, [1, 6, 8, 2, 9]); // => [6, 8, 9]
R.filter(R.has('active'), [{active: true}, {active: false}, {}]); // => [{active: true}, {active: false}]
const isEven = x => x % 2 === 0;
R.filter(isEven, [1, 2, 3, 4, 5, 6]); // => [2, 4, 6]Remove elements that satisfy a predicate function (opposite of filter).
/**
* @param {Function} predicate - Test function (a -> Boolean)
* @param {Array} list - List to filter
* @returns {Array} New list with non-matching elements
*/
R.reject(predicate, list)
// Examples
R.reject(x => x > 5, [1, 6, 8, 2, 9]); // => [1, 2]
R.reject(R.has('active'), [{active: true}, {active: false}, {}]); // => [{}]
const isOdd = x => x % 2 === 1;
R.reject(isOdd, [1, 2, 3, 4, 5, 6]); // => [2, 4, 6]Accumulate list elements into a single value.
/**
* @param {Function} reducer - Accumulator function ((acc, val) -> acc)
* @param {*} initialValue - Starting accumulator value
* @param {Array} list - List to reduce
* @returns {*} Final accumulated value
*/
R.reduce(reducer, initialValue, list)
// Examples
R.reduce(R.add, 0, [1, 2, 3, 4]); // => 10
R.reduce(R.multiply, 1, [2, 3, 4]); // => 24
R.reduce(R.max, -Infinity, [5, 2, 8, 1]); // => 8
// Building objects
const groupBy = (key, list) => R.reduce(
(acc, item) => R.assoc(item[key], [...(acc[item[key]] || []), item], acc),
{},
list
);Get the first element matching a predicate.
/**
* @param {Function} predicate - Test function (a -> Boolean)
* @param {Array} list - List to search
* @returns {* | undefined} First matching element or undefined
*/
R.find(predicate, list)
const users = [{id: 1, name: 'John'}, {id: 2, name: 'Jane'}];
R.find(R.propEq(2, 'id'), users); // => {id: 2, name: 'Jane'}
R.find(x => x > 10, [1, 5, 15, 3]); // => 15Get the index of the first element matching a predicate.
/**
* @param {Function} predicate - Test function (a -> Boolean)
* @param {Array} list - List to search
* @returns {Number} Index of match or -1 if not found
*/
R.findIndex(predicate, list)
R.findIndex(R.equals('world'), ['hello', 'world', 'foo']); // => 1
R.findIndex(x => x > 100, [10, 50, 150, 200]); // => 2Access list boundaries.
// Get first element
R.head(['a', 'b', 'c']); // => 'a'
R.head([]); // => undefined
// Get all but first element
R.tail(['a', 'b', 'c']); // => ['b', 'c']
R.tail([]); // => []
// Get last element
R.last(['a', 'b', 'c']); // => 'c'
R.last([]); // => undefined
// Get all but last element
R.init(['a', 'b', 'c']); // => ['a', 'b']
R.init([]); // => []Access element at specific index (supports negative indices).
/**
* @param {Number} index - Position to access
* @param {Array} list - List to index into
* @returns {*} Element at index or undefined
*/
R.nth(index, list)
const list = ['a', 'b', 'c', 'd'];
R.nth(1, list); // => 'b'
R.nth(-1, list); // => 'd' (last element)
R.nth(-2, list); // => 'c' (second to last)
R.nth(10, list); // => undefinedAdd elements to list boundaries.
// Add to end
R.append('new', ['a', 'b', 'c']); // => ['a', 'b', 'c', 'new']
// Add to beginning
R.prepend('new', ['a', 'b', 'c']); // => ['new', 'a', 'b', 'c']
// Curried usage
const addExclamation = R.append('!');
addExclamation(['Hello', 'World']); // => ['Hello', 'World', '!']Insert elements at specific positions.
// Insert single element
R.insert(2, 'NEW', [1, 2, 3, 4]); // => [1, 2, 'NEW', 3, 4]
// Insert multiple elements
R.insertAll(2, ['X', 'Y'], [1, 2, 3, 4]); // => [1, 2, 'X', 'Y', 3, 4]Modify list elements.
// Remove elements (start index, count)
R.remove(2, 1, [1, 2, 3, 4, 5]); // => [1, 2, 4, 5]
R.remove(1, 3, [1, 2, 3, 4, 5]); // => [1, 5]
// Update element at index
R.update(1, 'NEW', ['a', 'b', 'c']); // => ['a', 'NEW', 'c']
R.update(-1, 'LAST', ['a', 'b', 'c']); // => ['a', 'b', 'LAST']Transform element at specific index.
/**
* @param {Number} index - Position to modify
* @param {Function} fn - Transformation function
* @param {Array} list - List to modify
* @returns {Array} New list with element transformed
*/
R.adjust(index, fn, list)
R.adjust(1, R.toUpper, ['a', 'b', 'c']); // => ['a', 'B', 'c']
R.adjust(-1, R.multiply(10), [1, 2, 3]); // => [1, 2, 30]Extract portion of list.
/**
* @param {Number} from - Start index (inclusive)
* @param {Number} to - End index (exclusive)
* @param {Array} list - List to slice
* @returns {Array} Extracted portion
*/
R.slice(from, to, list)
R.slice(1, 3, [1, 2, 3, 4, 5]); // => [2, 3]
R.slice(2, -1, [1, 2, 3, 4, 5]); // => [3, 4]
R.slice(0, 2, 'hello'); // => 'he'Take or drop elements from list boundaries.
// Take from start
R.take(3, [1, 2, 3, 4, 5]); // => [1, 2, 3]
R.take(2, 'hello'); // => 'he'
// Take from end
R.takeLast(3, [1, 2, 3, 4, 5]); // => [3, 4, 5]
// Drop from start
R.drop(2, [1, 2, 3, 4, 5]); // => [3, 4, 5]
// Drop from end
R.dropLast(2, [1, 2, 3, 4, 5]); // => [1, 2, 3]Take/drop based on predicate.
const isLessThan5 = x => x < 5;
R.takeWhile(isLessThan5, [1, 2, 6, 7, 3]); // => [1, 2]
R.dropWhile(isLessThan5, [1, 2, 6, 7, 3]); // => [6, 7, 3]Split lists at specific points.
// Split at index
R.splitAt(2, [1, 2, 3, 4, 5]); // => [[1, 2], [3, 4, 5]]
R.splitAt(3, 'hello'); // => ['hel', 'lo']
// Split into chunks
R.splitEvery(2, [1, 2, 3, 4, 5, 6]); // => [[1, 2], [3, 4], [5, 6]]
R.splitEvery(3, 'abcdefgh'); // => ['abc', 'def', 'gh']Group elements by computed key.
/**
* @param {Function} keyFn - Function to compute grouping key (a -> String)
* @param {Array} list - List to group
* @returns {Object} Object with keys mapping to arrays of elements
*/
R.groupBy(keyFn, list)
const students = [
{name: 'Alice', grade: 'A'},
{name: 'Bob', grade: 'B'},
{name: 'Carol', grade: 'A'}
];
R.groupBy(R.prop('grade'), students);
// => {A: [{name: 'Alice', grade: 'A'}, {name: 'Carol', grade: 'A'}],
// B: [{name: 'Bob', grade: 'B'}]}
R.groupBy(R.length, ['cat', 'dog', 'elephant', 'ox']);
// => {'2': ['ox'], '3': ['cat', 'dog'], '8': ['elephant']}Split list into two arrays based on predicate.
/**
* @param {Function} predicate - Test function (a -> Boolean)
* @param {Array} list - List to partition
* @returns {Array} Two-element array [matching, non-matching]
*/
R.partition(predicate, list)
const isEven = x => x % 2 === 0;
R.partition(isEven, [1, 2, 3, 4, 5, 6]); // => [[2, 4, 6], [1, 3, 5]]
R.partition(R.has('active'), [{active: true}, {}, {active: false}]);
// => [[{active: true}, {active: false}], [{}]]Join two lists together.
R.concat([1, 2], [3, 4]); // => [1, 2, 3, 4]
R.concat('hello', ' world'); // => 'hello world'
// Curried
const addSuffix = R.concat(R.__, ' Inc.');
addSuffix('Acme Corp'); // => 'Acme Corp Inc.'Combine corresponding elements from multiple lists.
// Create pairs
R.zip([1, 2, 3], ['a', 'b', 'c']); // => [[1, 'a'], [2, 'b'], [3, 'c']]
// Combine with function
R.zipWith(R.add, [1, 2, 3], [4, 5, 6]); // => [5, 7, 9]
R.zipWith(R.concat, ['a', 'b'], ['1', '2']); // => ['a1', 'b1']Remove duplicates using different equality strategies.
// Remove duplicates (R.equals)
R.uniq([1, 1, 2, 2, 3]); // => [1, 2, 3]
R.uniq([1, '1', 2, '2']); // => [1, '1', 2, '2']
// Remove duplicates by computed value
R.uniqBy(Math.abs, [-1, 1, -2, 2, 3]); // => [-1, -2, 3]
R.uniqBy(R.prop('id'), [{id: 1, name: 'A'}, {id: 2, name: 'B'}, {id: 1, name: 'C'}]);
// => [{id: 1, name: 'A'}, {id: 2, name: 'B'}]
// Remove duplicates with custom equality
const sameLength = (a, b) => a.length === b.length;
R.uniqWith(sameLength, ['cat', 'dog', 'bat', 'fox']); // => ['cat', 'dog']Create array of numbers from start to end (exclusive).
/**
* @param {Number} from - Starting number (inclusive)
* @param {Number} to - Ending number (exclusive)
* @returns {Array} Array of numbers
*/
R.range(from, to)
R.range(1, 5); // => [1, 2, 3, 4]
R.range(0, 3); // => [0, 1, 2]
R.range(5, 5); // => []
// Useful for iterations
R.map(R.multiply(2), R.range(1, 6)); // => [2, 4, 6, 8, 10]Call function n times, collecting results in array.
/**
* @param {Function} fn - Function to call with index (Number -> a)
* @param {Number} n - Number of times to call
* @returns {Array} Array of results
*/
R.times(fn, n)
R.times(R.identity, 5); // => [0, 1, 2, 3, 4]
R.times(R.always('x'), 3); // => ['x', 'x', 'x']
R.times(x => x * x, 4); // => [0, 1, 4, 9]
// Generate test data
R.times(() => Math.random(), 3); // => [0.1, 0.8, 0.3] (example)Completely flatten nested arrays at all levels.
/**
* @param {Array} list - Nested array to flatten
* @returns {Array} Completely flattened array
*/
R.flatten(list)
R.flatten([1, [2, [3, [4]]]]); // => [1, 2, 3, 4]
R.flatten([[1, 2], [3, 4], [5]]); // => [1, 2, 3, 4, 5]
R.flatten([1, 2, 3]); // => [1, 2, 3] (already flat)Remove one level of nesting (shallow flatten).
/**
* @param {Array} list - Array to unnest one level
* @returns {Array} Array with one level removed
*/
R.unnest(list)
R.unnest([[1, 2], [3, 4], [5]]); // => [1, 2, 3, 4, 5]
R.unnest([1, [2, [3, 4]]]); // => [1, 2, [3, 4]]
R.unnest([1, 2, 3]); // => [1, 2, 3] (no nesting)Map and flatten in one operation.
/**
* @param {Function} fn - Function that returns a list (a -> [b])
* @param {Array} list - List to map over
* @returns {Array} Flattened result
*/
R.chain(fn, list)
const duplicate = x => [x, x];
R.chain(duplicate, [1, 2, 3]); // => [1, 1, 2, 2, 3, 3]
R.chain(R.split(''), ['hello', 'world']); // => ['h','e','l','l','o','w','o','r','l','d']Create sliding windows of consecutive elements.
/**
* @param {Number} size - Window size
* @param {Array} list - List to window
* @returns {Array} Array of windows
*/
R.aperture(size, list)
R.aperture(2, [1, 2, 3, 4, 5]); // => [[1,2], [2,3], [3,4], [4,5]]
R.aperture(3, [1, 2, 3, 4, 5]); // => [[1,2,3], [2,3,4], [3,4,5]]Flip rows and columns of 2D array.
R.transpose([[1, 'a'], [2, 'b'], [3, 'c']]);
// => [[1, 2, 3], ['a', 'b', 'c']]
R.transpose([[1, 2, 3], ['a', 'b', 'c']]);
// => [[1, 'a'], [2, 'b'], [3, 'c']]Test predicates across list elements.
// All elements match
R.all(x => x > 0, [1, 2, 3]); // => true
R.all(x => x > 0, [1, -1, 3]); // => false
// Any element matches
R.any(x => x > 10, [1, 15, 3]); // => true
R.any(x => x > 10, [1, 5, 3]); // => false
// No elements match
R.none(x => x < 0, [1, 2, 3]); // => true
R.none(x => x < 0, [1, -1, 3]); // => falseCheck if element exists in list.
R.includes(3, [1, 2, 3, 4]); // => true
R.includes('world', 'hello world'); // => true
R.includes({a: 1}, [{a: 1}, {b: 2}]); // => true (deep equality)These list functions provide the foundation for functional programming patterns in JavaScript, enabling powerful data transformations while maintaining immutability and composability.
Install with Tessl CLI
npx tessl i tessl/npm-ramda