1.  재귀 함수

🐰  함수 정의문 내에서 작성한 코드로 함수를 다시 호출하는 것

<script>
    let num = 0;
    function testFnc() {
        // 재귀 함수 호출을 적용하여 1부터 10까지의 값을 출력
        num++;
        document.write(num, '<br>');

        if(num === 10) return; // num 값이 10이면 종료

        console.log(`${num} 번째 호출`); // 10번째는 출력 안됨
        testFnc(); // 재귀 함수 호출
    }
    testFnc();
</script>


2.  콜백 함수  callback function

🐰  매개 변수로 전달하는 함수. 자바 스크립트는 함수도 하나의 자료형이므로 매개변수로 전달 할 수 있음

🐰  매개변수를 통해 함수를 받고, 그 함수를 통해 결과값을 호출함

<script>
    function callThreeTimes (callback) { // 함수를 선언
        for (let i = 0; i < 3; i++) {
            callback(i);
        }
    }

    function print(i) {
        console.log(`${i}번째 함수 호출`);
    }

    // 함수를 호출.
    callThreeTimes(print); // 매개변수로 함수를 전달. 함수를 매개변수로 사용할 경우 ()는 제외
    /* 0번째 함수 호출
    1번째 함수 호출
    2번째 함수 호출
     */
</script>

 


 콜백함수와 익명함수 
<script>
    function callThreeTimes (callback) { // 함수를 선언
        for (let i = 0; i < 3; i++) {
            callback(i);
        }
    }

    // 함수를 호출. 다른 언어에서는 낯선 방법이나 자바 스크립트나 코틀린 같은 이벤트 기반을 프로그래밍에서는 자주 사용.
    callThreeTimes(function (i) {
        console.log(`${i}번째 함수 호출`);
    });
</script>

 


콜백함수를 활용하는 함수 : forEach() 메서드


    🥕  배열이 갖고 있는 함수(메서드)로써 단순하게 배열 내부 요소를 사용해서 콜백함수를 호출

/* 콜백함수 기본형 */
function (value, index, array) { } //  매개 변수가 다 필요하지 않음.
<script>
    const numbers = [273, 52, 103, 32, 57];

    numbers.forEach(function (value, index, array) {
        // 매개변수로 value, index, array를 갖는 콜백함수를 사용
        console.log(`${index}번째 요소 : ${value}`);
    });

    // 함수 선언한 후에 매개 변수로 넘겨도 됨
    const call = function (value, index, array) {
        // 매개변수로 value, index, array를 갖는 콜백함수를 사용
        console.log(`${index}번째 요소 : ${value}`);
    }
    numbers.forEach(call);

    numbers.forEach(function (v, i) { // 매개변수로 v, i만 사용
        console.log(`${i}번째 요소 : ${v}`);
    })

    numbers.forEach(function(item) { // 매개변수로 v만 사용
        console.log(`${item}`)
    })
</script>

 


콜백함수를 활용하는 함수 : map() 메서드

 

   🥕  콜백함수에서 리턴한 값들을 기반으로 새로운 배열을 만들고 리턴

<script>
    // 배열을 선언
    let numbers = [273, 52, 103, 32, 57];

    // 배열의 모든 값을 제곱
    let numbers2 = numbers.map(function (value, index, array) {
        return value * value;
    });
    console.log(numbers2); // (5) [74529, 2704, 10609, 1024, 3249]

    // 출력
    numbers2.forEach(console.log); // value, index, array 순서대로 출력
    /*
    74529 0 (5) [74529, 2704, 10609, 1024, 3249]
    2704 1 (5) [74529, 2704, 10609, 1024, 3249]
    10609 2 (5) [74529, 2704, 10609, 1024, 3249]
    1024 3 (5) [74529, 2704, 10609, 1024, 3249]
    3249 4 (5) [74529, 2704, 10609, 1024, 3249]
     */

    // for문을 이용해서 제곱 배열 생성
    let numbers3 = [];
    for (const item of numbers) {
        numbers3.push(item * item);
    }
    console.log(numbers3); // (5) [74529, 2704, 10609, 1024, 3249]
</script>

 


콜백함수를 활용하는 함수: filter()


    🥕  콜백함수에서 리턴하는 값이 true인 것들만 모아서 새로운 배열을 만듦
           ➡️  콜백함수의 리턴 타입이 불 형 이어야 함

<script>
    const numbers = [11, 12, 13, 14, 15, 16];
    
    // 짝수만 추출
    const evenNumbers = numbers.filter(function (value) {
        return value % 2 === 0;
    });

    // 인덱스가 짝수만 추출
    const evenIndexs = numbers.filter(function (value, index) {
       return index % 2 === 0;
    });

    console.log(`원래 배열: ${numbers}`); // 원래 배열: 11,12,13,14,15,16
    console.log(`값이 짝수만 추출: ${evenNumbers}`); // 값이 짝수만 추출: 12,14,16
    console.log(`인덱스가 짝수만 추출: ${evenIndexs}`);  // 인덱스가 짝수만 추출: 11,13,15

    // 1의 자리가 3의 배수인 경우만 추출
    const evenNumbers2 = numbers.filter(function (value) {
        return (value % 10) % 3 === 0;
    });

    console.log(`1의 자리가 3의 배수: ${evenNumbers2}`); // 1의 자리가 3의 배수: 13,16
</script>

 


3.  화살표 함수  Arrow function


🐰  ES6에 추가된 내용으로 '=>'를 이용하여 함수를 간결하게 표현할 때 사용

    1) function 키워드를 생략
    2) 부등호 '='과 '>'를 합쳐서 코딩
    3) 항상 익명함수 형식으로 표현
    4) 단일 명령문일 경우 함수의 중괄호 {}와 return을 생략

 

 

Arrow function expressions - JavaScript | MDN

An arrow function expression is a compact alternative to a traditional function expression, with some semantic differences and deliberate limitations in usage:

developer.mozilla.org

<script>
    const doAddition1 = function (s1, s2) {
        return (s1 + s2) / 2;
    }
    console.log(doAddition1(2, 5)); // 3.5

    const doAddition2 = (s1, s2) => {
        return (s1 + s2) / 2;
    }
    console.log(doAddition2(2, 5)); // 3.5

    const doAddition3 = (s1, s2) => (s1 + s2) / 2;
    console.log(doAddition3(2, 5)); // 3.5
</script>


🐰  map(), filter() 함수처럼 단순한 형태의 콜백 함수를 쉽게 입력
🐰  function 키워드 대신 화살표(=>)를 사용

/* 기본형 */ 
(매개변수) => { }

 

💡  메소드 체이닝 : 메소드가 리턴하는 값을 기반으로 해서 메서드를 줄줄이 사용하는 것
<script>
    // 배열 선언
    let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    // numbers에서 2의 배수만 추출한 후, 제곱을 한 후에 로그에 출력.

    // 배열의 메소드를 연속적으로 사용. 메소드 체이닝.
    numbers.filter((value) => value % 2 === 0) // 2의 배수만 추출 / [0, 2, 4, 6, 8]
        .map((value) => value * value) // 제곱 추출 / [0 , 4, 6, 16, 36, 64]
        .forEach((value) => console.log(value)); // [0, 4, 16, 36, 64]
</script>

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1. 재귀함수

1) 팩토리얼  factorial

 n ! = n * (n-1) * (n-2) * ... * 1

 

 👾  이러한 팩토리얼을 구하는 방법은 2가지로 구분

       a. 반복문 사용

       b. 재귀 함수 사용

 

A. 반복문으로 팩토리얼 구하기

def factorial(n):
    output = 1
    for i in range(1, n+1):
        output *= i
    return output

print("1!:", factorial(1))
print("2!:", factorial(2))
print("3!:", factorial(3))
print("4!:", factorial(4))
'''
1!: 1
2!: 2
3!: 6
4!: 24
'''

 

 

B. 재귀 함수로 팩토리얼 구하기

   - 재귀 recursion 란 '자기 자신을 호출하는 것'을 의미

f(4) = 4 * f(3)
     = 4 * 3 * f(2)
     = 4 * 3 * 2 * f(1) * f(0)
     = 4 * 3 * 2 * 1 * 1
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)
        
print("1!:", factorial(1))
print("2!:", factorial(2))
print("3!:", factorial(3))
print("4!:", factorial(4))

 


 

2. 피보나치 수열  Fibonacci numbers

 

👩🏻‍💻  피보나치 수를 처음 연구한 것은 레오나르도 피오나치로 토끼 수의 증가에 대해서 이야기하면서 이 수에 대해 언급했다 

   

  📌  n 번째 달의 토끼 수

  • 첫 달에는 새로 태어난 토끼 한 쌍만이 존재한다.
  • 두 달 이상이 된 토끼는 번식 가능하다.
  • 번식 가능한 토끼 한 쌍은 매달 새끼 한 쌍을 낳는다.
  • 토끼는 죽지 않는다.

출처 : commons.wikimedia.org

 

 

    📌  1번째 수열 = 1

           2번째 수열 = 1

           n번째 수열 = (n-1)번째 수열 + (n-2)번째 수열

 

def fibonacci(n):
    if n == 1:
        return 1
    if n == 2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)
        
print("fibonnaci(1):", fibonacci(1))
print("fibonnaci(2):", fibonacci(2))
print("fibonnaci(3):", fibonacci(3))
print("fibonnaci(4):", fibonacci(4))
'''
fibonnaci(1): 1
fibonnaci(2): 1
fibonnaci(3): 2
fibonnaci(4): 3
'''

 

count = 0

def fibonacci(n):
    print("fibonacci({})를 구합니다.".format(n))
    global count
    count += 1
    
    if n == 1:
        return 1
    if n == 2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)
        
 fibonacci(10)
 print("---")
 print("fibonacci(10) 계산에 활용된 덧셈 횟수는 {}번입니다.".format(count))
 '''
fibonacci(10)를 구합니다.
fibonacci(9)를 구합니다.
...생략...
fibonacci(1)를 구합니다.
fibonacci(2)를 구합니다.
---
fibonacci(10) 계산에 활용된 덧셈 횟수는 109번입니다.
'''

 

💡  위와 같이 덧셈 횟수가 기하급수적으로 늘어나는 이유

 

 

 👾  다음과 같은 형태의 그림을 트리 tree 라고 한다.

 👾  트리에 있는 각각의 지점을 노드 node, 마지막 단계의 노드를 리프 leaf 

     ➡️  트리 내부에 있는 각각의 노드 값을 계산하려면 덧셈을 한 번씩 해야 함

      ➡️  한 번 구한 값은 그것으로 계산이 끝나는 게 아니라,

            한 번 구했던 값이라도 처음부터 다시 계산해야 함

      ➡️  이 때문에 계산 횟수가 기하급수적으로 늘어나는 것

 

 


 

💡 위의 예제에서 global count를 쓰는 이유

   

    - 파이썬은 함수 내부에서 함수 외부에 있는 변수를 참조하지 못한다.

    - 함수 내부에서 함수 외부에 있는 변수라는 것을 설명하려면 다음과 같은 구문을 사용해야 UnboundLocalError가 발생하지 않는다.

global 변수 이름

 


 

3. 메모화

👩🏻‍💻  한 번 계산한 값을 저장해 놓은 후, 이후에 다시 계산하지 않고 저장된 값을 활용하는 기술

# 메모 변수 생성
dic = {
    1: 1,
    2: 1
}

def fibonacci(n):
    if n in dic:
        # 메모가 되어 있으면 메모된 값을 리턴
        return dic[n]
    else:
        # 메모가 되어 있지 않으면 값을 구함
        output = fibonacci(n-1) + fibonacci(n-2)
        dic[n] = output
        return output
# 함수 호출        
print("fibonnaci(10):", fibonacci(10))
print("fibonnaci(20):", fibonacci(20))
print("fibonnaci(30):", fibonacci(30))
print("fibonnaci(40):", fibonacci(40))

 

 

👾  딕셔너리를 사용해서 한 번 계산한 값을 저장, 이를 메모한다고 표현

👾  딕셔너리에 값이 메모되어 있으면 처리를 수행하지 않고 곧바로 메모된 값을 돌려주면서 코드 속도를 빠르게 만든다.

 


 

4. 리스트 평탄화

👩🏻‍💻  중첩된 리스트가 있을 때 중첩을 모두 제거하고 풀어서 1차원 리스트로 만드는 것을 의미

 

def flatten(data):
    output = []
    for item in data:
        if type(item) == list:
            output += flatten(item)
        else:
            output.append(item)
    return output
    
 example = [[1,2,3], [4,[5,6]], 7, [8, 9]]
 print(flatten(example))
 # [1, 2, 3, 4, 5, 6, 7, 8, 9]

 

  ⚡️  append() 함수는 매개변수 하나를 리스트의 마지막 요소로 추가

         ➡️ append(리스트_자료형) 형태로 리스트를 전달하면 리스트 전체가 하나의 요소로서 추가됨

  ⚡️  += 연산자는 오른쪽에 있는 '리스트의 요소'를 하나하나 리스트에 추가

 

 

 

 

 

[ 내용 참고 : 책 '혼자 공부하는 파이썬']

+ Recent posts