ramdajs 주요 함수
흔히 사용될 수 있는 ramdajs 함수들을 알아본다
R.append
배열의 끝에 특정 요소를 추가한다
R.append('tests', ['write', 'more']); //=> ['write', 'more', 'tests']
vs vanillaJS
const arr = ['write', 'more'];
arr.push("tests");
console.log(arr); // ['write', 'more', 'tests']
R.prepend
배열의 처음에 특정 요소를 추가
R.prepend('fee', ['fi', 'fo', 'fum']); //=> ['fee', 'fi', 'fo', 'fum']
vs vanillaJS
const arr = ['fi', 'fo', 'fum'];
arr.unshift("fee");
console.log(arr); // ["fee", "fi", "fo", "fum"]
R.insert
배열의 특정 위치에 요소를 삽입
R.insert(2, 'x', [1,2,3,4]); //=> [1,2,'x',3,4]
vs vanillaJS
const arr = [1,2,3,4];
arr.splice(2,0,"x");
console.log(arr); // [1,2,'x',3,4]
R.pipe
순서대로 연결된 함수를 리턴
var f = R.pipe(Math.pow, R.negate, R.inc);
f(3, 4); // -(3^4) + 1
R.compose
역순으로 연결된 함수를 리턴
R.compose(Math.abs, R.add(1), R.multiply(2))(-4);
// => 7 cause) | (-4 * 2) + 1 |
R.flip
첫번째 두번째 인자의 위치 순서를 뒤집어 놓은 함수를 리턴. (전체 인자의 순서를 뒤집는 것은 아님)
var mergeThree = (a, b, c) => [].concat(a, b, c);
mergeThree(1, 2, 3); //=> [1, 2, 3]
R.flip(mergeThree)(1, 2, 3); //=> [2, 1, 3]
R.forEach
배열의 각 요소를 인자로 전달받는 특정 함수를 실행시키고 인자로 전달받았던 배열을 리턴한다
- Array.prototype.forEach 는 undefined 를 리턴
- 처리함수가 두번째 인자로 index 를 전달받지 못한다
var printXPlusFive = x => console.log(x + 5);
R.forEach(printXPlusFive, [1, 2, 3]); //=> [1, 2, 3]
// logs 6
// logs 7
// logs 8
vs vanillaJS
var printXPlusFive = x => console.log(x + 5);
[1,2,3].forEach(printXPlusFive);
R.map
리스트의 각 요소를 다른 값으로 매핑한다. Array.prototype.map 와 유사.
주의) 매핑함수의 2번째 인자로 index가 전달되지 않는다
var double = x => x * 2;
R.map(double, [1, 2, 3]); //=> [2, 4, 6]
R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6}
R.filter
배열의 특정 요소들만 필터링. Array.prototype.filter 와 유사
var isEven = n => n % 2 === 0;
R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
R.reduce
리스트의 각 요소를 순회하며 특정 값으로 축약한다/ Array.prototype.reduce 와 유사
R.reduce(R.subtract, 0, [1, 2, 3, 4]) // => ((((0 - 1) - 2) - 3) - 4) = -10
// - -10
// / \ / \
// - 4 -6 4
// / \ / \
// - 3 ==> -3 3
// / \ / \
// - 2 -1 2
// / \ / \
// 0 1 0 1
vanillaJS
[1, 2, 3, 4].reduce((a,c) => a-c, 0) // => ((((0 - 1) - 2) - 3) - 4) = -10
R.prop
객체의 특정 속성의 값을 리턴한다
R.prop('x', {x: 100}); //=> 100
R.prop('x', {}); //=> undefined
R.props
여러개의 속성의 값을 배열로 리턴
R.props(['x', 'y'], {x: 1, y: 2}); //=> [1, 2]
R.props(['c', 'a', 'b'], {b: 2, a: 1}); //=> [undefined, 1, 2]
var fullName = R.compose(R.join(' '), R.props(['first', 'last']));
fullName({last: 'Bullet-Tooth', age: 33, first: 'Tony'}); //=> 'Tony Bullet-Tooth'
R.find
배열에서 특정 조건을 만족하는 첫번재 요소를 리턴. Array.prototype.find 와 유사
var xs = [{a: 1}, {a: 2}, {a: 3}];
R.find(R.propEq('a', 2))(xs); //=> {a: 2}
R.find(R.propEq('a', 4))(xs); //=> undefined
vanillaJS
var xs = [{a: 1}, {a: 2}, {a: 3}];
xs.find(o => o.a === 2); //=> {a: 2}
xs.find(o => o.a === 4); //=> undefined
R.findIndex
배열에서 특정 조건을 만족하는 첫번째 요소의 인덱스를 리턴. Array.prototype.findIndex 와 유사
var xs = [{a: 1}, {a: 2}, {a: 3}];
R.findIndex(R.propEq('a', 2))(xs); //=> 1
R.findIndex(R.propEq('a', 4))(xs); //=> -1
R.propEq
속성의 값이 특정 값과 일치하는지 여부를 리턴
var abby = {name: 'Abby', age: 7, hair: 'blond'};
var fred = {name: 'Fred', age: 12, hair: 'brown'};
var rusty = {name: 'Rusty', age: 10, hair: 'brown'};
var alois = {name: 'Alois', age: 15, disposition: 'surly'};
var kids = [abby, fred, rusty, alois];
var hasBrownHair = R.propEq('hair', 'brown');
R.filter(hasBrownHair, kids); //=> [fred, rusty]
R.propIs
속성의 값의 타입이 특정 타입과 일치하는지 여부를 리턴
R.propIs(Number, 'x', {x: 1, y: 2}); //=> true
R.propIs(Number, 'x', {x: 'foo'}); //=> false
R.propIs(Number, 'x', {}); //=> false
R.range
특정 범위의 연속적인 자연수 배열을 리턴
R.range(1, 5); //=> [1, 2, 3, 4]
R.range(50, 53); //=> [50, 51, 52]
R.add
두 수의 합을 리턴
R.range(1, 5); //=> [1, 2, 3, 4]
R.range(50, 53); //=> [50, 51, 52]
R.and
두 값의 && 연산 결과를 리턴
R.and(true, true); //=> true
R.and(true, false); //=> false
R.and(false, true); //=> false
R.and(false, false); //=> false
R.or
두 값의 || 연산 결과를 리턴
R.or(true, true); //=> true
R.or(true, false); //=> true
R.or(false, true); //=> true
R.or(false, false); //=> false
R.partial
왼쪽부터 인자가 부분적용된 함수를 리턴
var multiply2 = (a, b) => a * b;
var double = R.partial(multiply2, [2]);
double(2); //=> 4
var greet = (salutation, title, firstName, lastName) =>
salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!';
var sayHello = R.partial(greet, ['Hello']);
var sayHelloToMs = R.partial(sayHello, ['Ms.']);
sayHelloToMs('Jane', 'Jones'); //=> 'Hello, Ms. Jane Jones!'
R.partialRight
오른쪽부터 인자가 부분적용된 함수를 리턴
var greet = (salutation, title, firstName, lastName) =>
salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!';
var greetMsJaneJones = R.partialRight(greet, ['Ms.', 'Jane', 'Jones']);
greetMsJaneJones('Hello'); //=> 'Hello, Ms. Jane Jones!'
R.partition
특정 기준으로 리스트를 둘로 나눔
R.partition(R.contains('s'), ['sss', 'ttt', 'foo', 'bars']);
// => [ [ 'sss', 'bars' ], [ 'ttt', 'foo' ] ]
R.partition(R.contains('s'), { a: 'sss', b: 'ttt', foo: 'bars' });
// => [ { a: 'sss', foo: 'bars' }, { b: 'ttt' } ]
R.equals
두 값을 비교, 순환참조 객체도 비교 가능
R.equals(1, 1); //=> true
R.equals(1, '1'); //=> false
R.equals([1, 2, 3], [1, 2, 3]); //=> true
var a = {}; a.v = a;
var b = {}; b.v = b;
R.equals(a, b); //=> true
R.contains
리스트에 특정 요소가 포함되는지 여부를 리턴. 내부적으로 R.equals 를 이용해 비교
R.contains(3, [1, 2, 3]); //=> true
R.contains(4, [1, 2, 3]); //=> false
R.contains({ name: 'Fred' }, [{ name: 'Fred' }]); //=> true
R.contains([42], [[42]]); //=> true
R.any
리스트에서 특정 조건을 만족하는 요소가 있는지 여부를 리턴
var lessThan0 = R.flip(R.lt)(0);
var lessThan2 = R.flip(R.lt)(2);
R.any(lessThan0)([1, 2]); //=> false
R.any(lessThan2)([1, 2]); //=> true
R.tail
머리 빼고 리턴
R.tail([1, 2, 3]); //=> [2, 3]
R.tail([1, 2]); //=> [2]
R.tail([1]); //=> []
R.tail([]); //=> []
R.tail('abc'); //=> 'bc'
R.tail('ab'); //=> 'b'
R.tail('a'); //=> ''
R.tail(''); //=> ''
R.init
배열의 마지막 요소만 뺀 앞 부분 전부 리턴
R.init([1, 2, 3]); //=> [1, 2]
R.init([1, 2]); //=> [1]
R.init([1]); //=> []
R.init([]); //=> []
R.init('abc'); //=> 'ab'
R.init('ab'); //=> 'a'
R.init('a'); //=> ''
R.init(''); //=> ''
R.split
문자열을 특정 기준으로 나눔, String.prototype.split 과 유사
var pathComponents = R.split('/');
R.tail(pathComponents('/usr/local/bin/node')); //=> ['usr', 'local', 'bin', 'node']
R.split('.', 'a.b.c.xyz.d'); //=> ['a', 'b', 'c', 'xyz', 'd']
R.clone
깊은복사
var objects = [{}, {}, {}];
var objectsClone = R.clone(objects);
objects === objectsClone; //=> false
objects[0] === objectsClone[0]; //=> false
R.isNil
undefined
or null
체크
R.isNil(null); //=> true
R.isNil(undefined); //=> true
R.isNil(0); //=> false
R.isNil([]); //=> false
R.complement
true
or false
를 리턴하는 함수를 인자로 받아서 그 반대 결과를 리턴하는 함수를 만든다
var isNotNil = R.complement(R.isNil);
isNil(null); //=> true
isNotNil(null); //=> false
isNil(7); //=> false
isNotNil(7); //=> true
R.concat
두 배열을 병합
R.concat('ABC', 'DEF'); // 'ABCDEF'
R.concat([4, 5, 6], [1, 2, 3]); //=> [4, 5, 6, 1, 2, 3]
R.concat([], []); //=> []
R.T
항상 true
리턴
R.T(); //=> true
R.F
항상 false
리턴
R.F(); //=> false
R.always
항상 주어진 값을 리턴
var t = R.always('Tee');
t(); //=> 'Tee'
R.cond
true를 만날 때까지 조건을 체크, true를 만나면 해당 함수를 실행, true를 못 만나면 undefined 리턴. switch
문과 비슷
var fn = R.cond([
[R.equals(0), R.always('water freezes at 0°C')],
[R.equals(100), R.always('water boils at 100°C')],
[R.T, temp => 'nothing special happens at ' + temp + '°C']
]);
fn(0); //=> 'water freezes at 0°C'
fn(50); //=> 'nothing special happens at 50°C'
fn(100); //=> 'water boils at 100°C'
R.ifElse
if else 구문과 비슷
var incCount = R.ifElse(
R.has('count'),
R.over(R.lensProp('count'), R.inc),
R.assoc('count', 1)
);
incCount({}); //=> { count: 1 }
incCount({ count: 1 }); //=> { count: 2 }
R.sort
조건에 따라 배열을 정렬
var diff = function(a, b) { return a - b; };
R.sort(diff, [4,2,7,5]); //=> [2, 4, 5, 7]
R.flatten
이상한? 배열을 받아서 1차원 배열로 리턴
R.flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]);
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
R.keys
모든 속성을 배열로 리턴, Object.keys
와 유사
R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c']
R.values
모든 값을 배열로 리턴, Object.values
와 유사
R.values({a: 1, b: 2, c: 3}); //=> [1, 2, 3]
R.trim
문자열 양끝의 공백제거
R.trim(' xyz '); //=> 'xyz'
vanillaJS
' xyz '.trim()
R.all
모든 요소가 어떤 조건을 만족하는 지 체크
var equals3 = R.equals(3);
R.all(equals3)([3, 3, 3, 3]); //=> true
R.all(equals3)([3, 3, 1, 3]); //=> false
R.curry
원하는 순서대로 인자 하나씩 부분적용 가능, R.__
를 이용해 해당인자 잠시 비워두기도 가능. R.__
는 R.curry
를 통한 함수에서만 사용이 가능
var g = R.curry((a,b,c) => a-b-c);
// 아래 예시는 모두 동일한 결과
g(1,2,3)
g(1)(2)(3)
g(1,2)(3)
g(1)(2,3)
// 2번째 인자 먼저 적용하고 싶으면
g(R.__, 2)(1)(3)
// 3번째 인자 먼저 적용하려면
g(R.__, R.__, 3)(1)(2)
R.drop
앞쪽부터 n개의 요소를 제거한다
R.drop(1, ['foo', 'bar', 'baz']); //=> ['bar', 'baz']
R.drop(2, ['foo', 'bar', 'baz']); //=> ['baz']
R.drop(3, ['foo', 'bar', 'baz']); //=> []
R.drop(4, ['foo', 'bar', 'baz']); //=> []
R.drop(3, 'ramda'); //=> 'da'
R.dropLast
뒤쪽부터 n개의 요소를 제거한다
R.dropLast(1, ['foo', 'bar', 'baz']); //=> ['foo', 'bar']
R.dropLast(2, ['foo', 'bar', 'baz']); //=> ['foo']
R.dropLast(3, ['foo', 'bar', 'baz']); //=> []
R.dropLast(4, ['foo', 'bar', 'baz']); //=> []
R.dropLast(3, 'ramda'); //=> 'ra'
Comments