타입스크립트 기초 - 17

Stulta Amiko·2022년 7월 28일
0

타입스크립트 기초

목록 보기
17/24
post-thumbnail

배열 다루기

prepend / append

import * as R from 'ramda'

const array: number[] = [3,4]
const new_arr_p = R.prepend(1)(array)
const new_arr_a = R.append(1)(array)

console.log(new_arr_p)
console.log(new_arr_a)

실행결과
[ 1, 3, 4 ][ 3, 4, 1 ]

prepend는 배열의 앞쪽에 값을 추가하는것이고
append는 배별의 뒤쪽에 값을 추가하는 함수이다.


flatten

flatten 함수는 복잡한 배열을 평탄화 시켜주는 역할을 한다.

import * as R from 'ramda'

const arr = R.range(1,3).map((x: number) => {
    return R.range(1,3).map((y: number) => {
        return [x,y]
    })
})

console.log(arr)

const flat_arr = R.flatten(arr)
console.log(flat_arr)

실행결과
[ [ [ 1, 1 ], [ 1, 2 ] ], [ [ 2, 1 ], [ 2, 2 ] ] ] ,
[
1, 1, 1, 2,
2, 1, 2, 2
]

보이는 대로 복잡한 배열을 저런식으로 평탄화 시킬 수 있다.


unnest

unnest 함수는 완벽하게 평탄화 시키지는 않고 좀 더 정교한 방식으로 배열을 평탄화 시킨다.

import * as R from 'ramda'

const arr = R.range(1,3).map((x: number) => {
    return R.range(1,3).map((y: number) => {
        return [x,y]
    })
})

console.log(arr)

const unnest_arr = R.unnest(arr)
console.log(unnest_arr)

//@ts-ignore
const unnest_arr_R = R.pipe(R.unnest,R.unnest)(arr)
console.log(unnest_arr_R)

실행결과
[ [ [ 1, 1 ], [ 1, 2 ] ], [ [ 2, 1 ], [ 2, 2 ] ] ]
[ [ 1, 1 ], [ 1, 2 ], [ 2, 1 ], [ 2, 2 ] ][ 1, 1, 1, 2, 2, 1, 2, 2 ]

위와 같이 좀 더 정교하게 분해하는 모습을 볼 수 있다.

처음에는 한번만 돌리고 두번째는 두번 돌렸을때 결과이다.


sort

sort는 이름에서 알 수 있듯이 배열을 오름차순이나 내림차 순으로 정렬해 주는 함수이다.

import * as R from 'ramda'

type voidToNumberFunc = () => number
const makeRandomNumber = (max: number): voidToNumberFunc =>
    (): number => Math.floor(Math.random() * max)

const arr = R.range(1,6).map(makeRandomNumber(100))
const sortedArr = R.sort((a: number,b: number): number => a-b)(arr)

console.log(arr,sortedArr)

콜백에 마이너스 값이면 오름차순 0이나 플러스값이면 내림차 순이라고 하는데
무슨말인지 잘모르겠다. 이대로 실행하면 오름차순으로 정렬되어 나오긴한다.

좀더 보니깐 b-a로 하면 내림차순 구현이 된다.


sortBy

배열에 담긴 아이템이 객체라면 특정 속성값에 따라 정렬해야하는데 이때
sortBy 함수를 사용한다.

import * as R from 'ramda'
import { IPerson,makeRandomIPerson } from './model/person'
import { displayPerson } from './displayPerson'

const persons: IPerson[] = R.range(1,5).map(makeRandomIPerson)
const nameSortedPersons = R.sortBy(R.prop('name'))(persons)
const ageSortedPersons = R.sortBy(R.prop('age'))(persons)

displayPerson('sorted by name')(nameSortedPersons)
displayPerson('sorted by age')(ageSortedPersons)

sortby-test.ts

import * as R from 'ramda'
import { IPerson } from './model/person'

export const displayPerson = (prefix: string) => R.pipe(
    R.map((person: IPerson) => ({name: person.name,age: person.age})),
    R.tap(o => console.log(prefix,o))
)as any

displayPerson.ts

실행결과
sorted by name [
{ name: 'Alejandro Beck', age: 41 },
{ name: 'Eleanor Colon', age: 18 },
{ name: 'Genevieve Bishop', age: 64 },
{ name: 'Troy Ward', age: 42 }
]
sorted by age [
{ name: 'Eleanor Colon', age: 18 },
{ name: 'Alejandro Beck', age: 41 },
{ name: 'Troy Ward', age: 42 },
{ name: 'Genevieve Bishop', age: 64 }
]


sortWith

sortBy는 항상 오름차순으로만 정렬한다.
sortWith 함수는 ascend,descend를 이용해서 오름차순과 내림차순 정렬을 할 수있다.

import * as R from 'ramda'
import { IPerson,makeRandomIPerson } from './model/person'
import { displayPerson } from './displayPerson'

const persons: IPerson[] = R.range(1,5).map(makeRandomIPerson)
//@ts-ignore
const nameSortedPerson = R.sortWith([R.descend(R.prop(('name')))])(persons)

displayPerson('sorted by name')(nameSortedPerson)

람다 라이브러리 자체가 js기반이라 그런지는 모르겠는데
알 수 없는 오류가 자꾸 발생한다.
너무 화난다.
이런식으로 하면 내림차순으로 구현이된다.
애초에 뭐 공식사이트에 있는 예제를 박아도 똑같은 오류가 난다

조합 논리 이해하기

chain 조합자

chain 조합자는 함수를 매개변수로 받아 동작하는 함수로
매개변수가 한개일때와 두개일때의 동작이 다르다.

import * as R from 'ramda'

const array = [1,2,3]

R.pipe(
    R.chain(n => [n,n]),
    R.tap(n => console.log(n))
)(array)

R.pipe(
    R.chain(R.append,R.head),
    R.tap(n => console.log(n))
)(array)

실행결과
[ 1, 1, 2, 2, 3, 3 ][ 1, 2, 3, 1 ]

둘이 보면 실행결과가 다른데

매개변수가 한개일때는 아래 코드와 같이 동작한다.

import * as R from 'ramda'

const array = [1,2,3]

const flatMap = (f) => R.pipe(
    R.map(f),
    R.flatten
)

R.pipe(
    flatMap(n => [n,n]),
    R.tap(n => console.log(n))
)(array)

실행결과
[ 1, 1, 2, 2, 3, 3 ]

그리고 매개변수가 두개일때는 아래와 같이 동작한다.

import * as R from 'ramda'

const array = [1,2,3]

const chainTwoFunc = (firstFn,SecondFn) => (x) => firstFn(SecondFn(x),x)

R.pipe(
    chainTwoFunc(R.append,R.head),
    R.tap(n => console.log(n))
)(array)

실행결과
[ 1, 2, 3, 1 ]


flip 조합자

flip 함수는 2차 고차 함수의 매개변수 순서를 서로 바꿔주는 역할을 한다.

const flip = cb => a => b => cb(b)(a)

import * as R from 'ramda'

const flip = cb => a => b => cb(b)(a)
const reverseSubtract = flip(R.subtract)

const new_arr = R.pipe(
    R.map(reverseSubtract(10)),
    R.tap(n => console.log(n))
)(R.range(1,10))

flip을 풀어서 구현했다.


identity 조합자

identity는 엄청 단순하게 생겼다.

const identity = x => x

구조상 함수가 꼭 필요한 자리에 넣어줄 수 있는 조합자이다.

import * as R from 'ramda'
import { flatMap } from './flatmap'


const unnest = flatMap(R.identity)

const arr = [[1],[2],[3]]
R.pipe(
    unnest,
    R.tap(n => console.log(n))
)(arr)

flatMap 함수가 요구하는 콜백함수 자리에 identity를 넣은 모습을 볼 수 있다.


always 조합자

always 조합자는 두개의 고차함수 파라미터중 첫번째 파라미터를 반환한다.

const always = x => y => x

import * as R from 'ramda'

const always = a => b => a
const flip = cb => a => b => cb(b)(a)

const first = <T>(a: T) => (b: T): T => always(a)(b)
const second = <T>(a: T) => (b: T): T => flip(always)(a)(b)

console.log(
    first(1)(2),
    second(1)(2)
)

실행결과
1 2

flip은 파라미터의 순서를 바꿔준다
따라서 위와같은 실행결과가 나오게된다.


applyTo 조합자

applyTo 조합자는 특별하게 값을 첫 번째 매개변수로 이값을 입력으로 하는 콜백 함수를 두 번째 매개변수로 받아 다음 코드처럼 동작한다.

뭐라는거지

const applyTo = value => cb => cb(value)

위와같은 방식으로 작용한다고 한다.

import * as R from 'ramda'

const T = value => R.pipe(
    R.applyTo(value),
    R.tap(value => console.log(value))
)

const value100 = T(100)
const sameValue = value100(R.identity)
const add1Value = value100(R.add(1))

실행결과
100 101

위와같은 방식으로 동작한다.


ap 조합자

ap 조합자는 콜백 함수들의 배열을 첫 번째 매개변수로 배열을 두번째 매개변수로 입력받는 2차 고차 함수이다.

const ap = ([callback]) => arr => [callback] (arr)

ap 에 콜백함수가 하나일때는 map 처럼 동작한다.

import * as R from 'ramda'

const callAndAppend = R.pipe(
    R.ap([R.multiply(2)]),
    R.tap(n => console.log(n))
)

const input = [1,2,3]
const result = callAndAppend(input)

실행결과
[2,4,6]

하지만 콜백이 두개일때는
R.chain(n =>[n,n]) 처럼 동작한다.
두 개일때 두 콜백 함수를 적용한 각각의 배열을 만든 다음에 연산이 끝나면 배열을 모두 통합해서 하나로 만들어준다.

import * as R from 'ramda'

const callAndAppend = R.pipe(
    R.ap([R.multiply(2),R.add(10)]),
    R.tap(a => console.log(a))
)

const input = [1,2,3]
const result =  callAndAppend(input)

실행결과
[2,4,6,11,12,13]

위 코드가 그 예시이다.

처음에 2를 곱해준값을 가지고 그다음에 원본 배열에 10을 더한 값을 가지는것을 볼 수 있다.

0개의 댓글