비밀번호

  • [PHP] 코드 줄이기

  • 짧은주소 : http://dreamphp.com/s/b0b

  • 작 성 자 : BiHonHomepage

  • 조 회 수 : 3191

  • 등 록 일 : 2012-11-05 20:12:21

  • PHP스쿨에 올라온 질문 중에서 반복문... 더 줄일 수 있을까요?? 라는 질문을 보고 참고삼아 적습니다.

    $xxx_a_a_0 = $xxx_a_a_1 + $xxx_a_a_2 + $xxx_a_a_3 + $xxx_a_a_4 + $xxx_a_a_5 + $xxx_a_a_6 + $xxx_a_a_7 + $xxx_a_a_8 + $xxx_a_a_9 + $xxx_a_a_10 + $xxx_a_a_11 + $xxx_a_a_12 + $xxx_a_a_13 + $xxx_a_a_14 + $xxx_a_a_15;

    $xxx_a_a_1부터 $xxx_a_a_15까지 변수의 합을 구하는 코드입니다.
    코드를 보면 '숫자'만 바뀌고, 그전의 문자열은 같습니다.
    이 경우 반복문가변 변수를 이용해 아래처럼 간단하게 줄일 수 있습니다.

    for ($i=1,$xxx_a_a_0=0;$i<16;$i++) $xxx_a_a_0+= ${'xxx_a_a_'.$i};

    $i는 1부터 15까지 반복입니다.
    $xxx_a_a_0의 값은 0으로 초기화합니다.
    반복문 내 가변 변수를 이용해 그 값을 $xxx_a_a_0에 더합니다.

    그럼 아래처럼 같은 형태로 반복되는 코드는 어떻게 줄일 수 있을까요?

    $xxx_a_a_0 = $xxx_a_a_1 + $xxx_a_a_2 + $xxx_a_a_3 + $xxx_a_a_4 + $xxx_a_a_5 + $xxx_a_a_6 + $xxx_a_a_7 + $xxx_a_a_8 + $xxx_a_a_9 + $xxx_a_a_10 + $xxx_a_a_11 + $xxx_a_a_12 + $xxx_a_a_13 + $xxx_a_a_14 + $xxx_a_a_15;
    $xxx_a_b_0 = $xxx_a_b_1 + $xxx_a_b_2 + $xxx_a_b_3 + $xxx_a_b_4 + $xxx_a_b_5 + $xxx_a_b_6 + $xxx_a_b_7 + $xxx_a_b_8 + $xxx_a_b_9 + $xxx_a_b_10 + $xxx_a_b_11 + $xxx_a_b_12 + $xxx_a_b_13 + $xxx_a_b_14 + $xxx_a_b_15;
    $xxx_b_a_0 = $xxx_b_a_1 + $xxx_b_a_2 + $xxx_b_a_3 + $xxx_b_a_4 + $xxx_b_a_5 + $xxx_b_a_6 + $xxx_b_a_7 + $xxx_b_a_8 + $xxx_b_a_9 + $xxx_b_a_10 + $xxx_b_a_11 + $xxx_b_a_12 + $xxx_b_a_13 + $xxx_b_a_14 + $xxx_b_a_15;
    $xxx_b_b_0 = $xxx_b_b_1 + $xxx_b_b_2 + $xxx_b_b_3 + $xxx_b_b_4 + $xxx_b_b_5 + $xxx_b_b_6 + $xxx_b_b_7 + $xxx_b_b_8 + $xxx_b_b_9 + $xxx_b_b_10 + $xxx_b_b_11 + $xxx_b_b_12 + $xxx_b_b_13 + $xxx_b_b_14 + $xxx_b_b_15;

    1부터 15까지의 반복은 전과 같고, 중간 이름(a_a, a_b, b_a, b_b)만 다릅니다.
    처음 줄인 코드를 이용해 아래처럼 줄일 수 있지요.

    for ($i=1,$xxx_a_a_0=0;$i<16;$i++) $xxx_a_a_0+= ${'xxx_a_a_'.$i};
    for ($i=1,$xxx_a_b_0=0;$i<16;$i++) $xxx_a_b_0+= ${'xxx_a_b_'.$i};
    for ($i=1,$xxx_b_a_0=0;$i<16;$i++) $xxx_b_a_0+= ${'xxx_b_a_'.$i};
    for ($i=1,$xxx_b_b_0=0;$i<16;$i++) $xxx_b_b_0+= ${'xxx_b_b_'.$i};

    내용이 길어지면 위 코드도 그만큼 Copy&Paste 후 한 줄에 세 부분씩 수정해야 합니다.
    코드가 길어질수록 수정하는 번거로움을 피하기 위해선 중간 부분도 변수 처리하면 됩니다.

    for ($key='a_a',$i=1,${'xxx_'.$key.'_0'}=0;$i<16;$i++) ${'xxx_'.$key.'_0'}+= ${'xxx_'.$key.'_'.$i};
    for ($key='a_b',$i=1,${'xxx_'.$key.'_0'}=0;$i<16;$i++) ${'xxx_'.$key.'_0'}+= ${'xxx_'.$key.'_'.$i};
    for ($key='b_a',$i=1,${'xxx_'.$key.'_0'}=0;$i<16;$i++) ${'xxx_'.$key.'_0'}+= ${'xxx_'.$key.'_'.$i};
    for ($key='b_b',$i=1,${'xxx_'.$key.'_0'}=0;$i<16;$i++) ${'xxx_'.$key.'_0'}+= ${'xxx_'.$key.'_'.$i};

    한 줄 그대로 복사 후 $key만 변경하면 되니까 간편해졌죠?
    이제 위 코드도 좀 더 간결하게 바꿔보겠습니다. 바로 함수화!
    함수에서는 $GLOBALS 변수로 접근하면 됩니다. 참고 문서

    function sum($key) { for($i=1,$sum=0;$i<16;$i++) $sum+=$GLOBALS['xxx_'.$key.'_'.$i]; return $sum; }
    $xxx_a_a_0 = sum('a_a');
    $xxx_a_b_0 = sum('a_b');
    $xxx_b_a_0 = sum('b_a');
    $xxx_b_b_0 = sum('b_b');

    이 경우도 코드가 길어지면 앞부분, 뒷부분을 수정해야 해서 번거롭겠죠?
    변수에 바로 할당하면 굳이 합계를 반환할 필요가 없겠죠?

    function sum($key) { for($i=1,$sum=0;$i<16;$i++) $sum+=$GLOBALS['xxx_'.$key.'_'.$i]; $GLOBALS['xxx_'.$key.'_0'] = $sum; }
    sum('a_a');
    sum('a_b');
    sum('b_a');
    sum('b_b');

    처음보다 많이 줄어들었죠?
    그런데 더해야 하는 변수가 아래처럼 많으면?

    function sum($key) { for($i=1,$sum=0;$i<16;$i++) $sum+=$GLOBALS['xxx_'.$key.'_'.$i]; $GLOBALS['xxx_'.$key.'_0'] = $sum; }
    sum('a_a');
    sum('a_b');
    sum('b_a');
    sum('b_b');
    sum('c_a');
    sum('c_b');
    sum('c_c');
    sum('d_a');
    sum('d_b');
    sum('e_a');
    sum('e_b');
    sum('f_a');
    sum('f_b');
    sum('f_c');
    sum('f_d');
    sum('g_a');
    sum('g_b');
    sum('g_c');
    sum('g_d');
    sum('g_e');
    sum('h_a');
    sum('i_a');
    sum('i_b');
    sum('i_c');
    sum('i_d');
    sum('i_e');
    sum('i_f');
    sum('i_g');
    sum('i_h');
    sum('i_i');
    sum('i_j');
    sum('i_k');
    sum('i_l');
    sum('i_m');
    sum('i_n');
    sum('j_a');
    sum('j_b');
    sum('j_c');
    sum('j_d');
    sum('j_e');
    sum('j_f');
    sum('j_g');
    sum('j_h');
    sum('j_i');
    sum('j_j');
    sum('j_k');
    sum('j_l');
    sum('j_m');
    sum('j_n');
    sum('j_o');
    sum('j_p');
    sum('j_q');
    sum('j_r');
    sum('j_s');

    위 코드는 어떻게 줄일 수 있을까요?
    여기에서는 배열을 이용하면 편합니다.

    function sum($key) { for($i=1,$sum=0;$i<16;$i++) $sum+=$GLOBALS['xxx_'.$key.'_'.$i]; $GLOBALS['xxx_'.$key.'_0'] = $sum; }
    foreach ( array('a_a','a_b','b_a','b_b','c_a','c_b','c_c','d_a','d_b','e_a','e_b','f_a','f_b','f_c','f_d',
    'g_a','g_b','g_c','g_d','g_e','h_a','i_a','i_b','i_c','i_d','i_e','i_f','i_g','i_h','i_i','i_j','i_k','i_l',
    'i_m','i_n','j_a','j_b','j_c','j_d','j_e','j_f','j_g','j_h','j_i','j_j','j_k','j_l','j_m','j_n','j_o','j_p',
    'j_q','j_r','j_s') as $key ) sum($key);

    편하다고 했는데 막상 늘어놓으니 그렇게 편해 보이지는 않는군요.
    그래도 확실히 코드가 줄어들긴 줄어들었죠?
    이 코드를 더 줄일 수 있습니다.

    a는 a부터 b까지, b는 a부터 b까지, c는 a부터 c까지와 같이 두 번째는 a부터 시작하죠.
    첫 문자와 수를 입력해 반복시키면 되겠죠?

    function test($_k,$_c)
    {
        for($_i=0;$_i<$_c;$_i++)
        {
            echo $_k.'_'.chr(97+$_i).'<br />';
        }
    }
    test('a',2);
    test('b',2);

    ▶ 실행 결과
    a_a
    a_b
    b_a
    b_b

    chr() 함수는 지정한 숫자에 해당하는 아스키코드를 반환합니다.
    'a'가 97이기 때문에 반복문 내에서 97+0=97→a, 97+1=98→b가 구해집니다.

    function sum($key) { for($i=1,$sum=0;$i<16;$i++) $sum+=$GLOBALS['xxx_'.$key.'_'.$i]; $GLOBALS['xxx_'.$key.'_0'] = $sum; }
    function code($_k,$_c) { for ($_i=0;$_i<$_c;$_i++) sum($_k.'_'.chr(97+$_i)); }
    code('a',2);
    code('b',2);
    code('c',3);
    code('d',2);
    code('e',2);
    code('f',4);
    code('g',5);
    code('h',1);
    code('i',14);
    code('j',19);

    배열을 이용해 줄이는 방법은 위에 언급했죠?
    그리고 여기서도 보면 a부터 j까지 순서대로 반복되죠?
    결국, 뒤의 숫자만 있으면 되겠죠?

    함수명(array(2,2,3,2,2,4,5,1,14,19));
    또는
    함수명(2,2,3,2,2,4,5,1,14,19); // 간편하게 func_get_args() 이용

    배열의 크기만큼 반복하며 지정한 숫자만큼 반복.
    줄이는 방법은 이미 위에 전부 적었기 때문에 실제 함수는 생략합니다.

    혹시 이 글을 보고 짧게 줄여본 분은 코드를 댓글로 남겨주시면… /박수

    ▶ 힌트
    - 반복문 3개
  • 2012-11-07 17:07:10

  • 멍우연

  • 잉...  배열 이용해서 function 만들고 for문 돌리고 func_get_args()도 써봤는데...
    논리오류만 나네요... ㅜ ㅜ      계속 아무런 값도 안나오네요.. 흑흑...

  • 2012-11-08 14:51:39

  • BiHonHomepage

  • 스쿨에 남긴 댓글의 코드 중에서 'a'부터 순서대로 증가하는 코드 이용하면 됩니다.
    차근차근 해보세요.

  • 2012-11-12 11:14:23

  • 멍우연

  • function args($args)  {
    $args = func_get_args();
    for($i=1,$args=0; $i<11; $i++)  $args+=$GLOBALS['xxx_'.$args.'_'.$i];
       $GLOBALS['xxx_'.$args.'_'.$i] = $args;  }
    foreach( array('2','2','3','2','2','4','5','1','14','19') as $args ) args($args);


    function sum2($args)  {
    for($i=1, $sum=0;  $i<11; $i++) $sum+=$GLOBALS['code('.$args.')'.$i];
       $GLOBALS['code('.$args.')'] = $sum;
    }
    foreach(array(2,2,3,2,2,4,5,1,14,19) as $args ) sum($args);  


    function args($args) {
    $args = func_get_args();
    for($i=$args=1; $i<11; $i++)$args+=$GLOBALS['code('.$args.')'];
    $GLOBALS['code('.$args.')'] = $args; }
    foreach(array('2','2','3','2','2','2','4','5','1','14','19') as $args ) args($args);


    댓글의 코드 보고 제가 한번 짜본 코드들 입니다...
    구문오류가 아닌 논리오류라서 어디가 잘못되었는지 어렵네요.. ㅜ ㅜ
    아무런 값도 출력이 되지 않네요...    Null 값 뜨는지 공백표시 되네요 ㅎㅎ;

  • 2012-11-12 12:51:15

  • BiHonHomepage

  • 박수!

    소스 상단에 error_reporting(E_ALL);을 추가하고 실행해보세요.
    오류만 잡아도 실력 향상에 도움이 되니까요.

    첫 번째 코드를 봐요.

    function args($args)  {
    $args = func_get_args();
    for($i=1,$args=0; $i<11; $i++)  $args+=$GLOBALS['xxx_'.$args.'_'.$i];
      $GLOBALS['xxx_'.$args.'_'.$i] = $args;  }
    foreach( array('2','2','3','2','2','4','5','1','14','19') as $args ) args($args);



    foreach( array('2','2','3','2','2','4','5','1','14','19') as $args )를 실행했을 때
    $args는 순서대로 2, 2, 3, 2, 2, 4, 5, 1, 14, 19 입니다.
    이것을 args() 함수에 던져주는데 함수 내에서 $args = func_get_args(); 같은 변수를 이용하는군요.
    그런데 for()의 조건을 보면 $args=0으로 다시 할당했어요.
    결국, 함수에 어떤 값을 던져도 'xxx_0_1'부터 'xxx_0_10'까지 반복합니다.
    해당 변수가 없으니 값도 없겠죠? 반복 끝내도 마찬가지. $xxx_0_11 = 0;

    ※ 변수 구분은 확실하게!


    두 번째 코드. 함수명이 틀렸죠? 함수명을 같게 변경했다고 가정합니다.
    여기에서는 전혀 엉뚱한 변수명을 사용하죠? 'code(2)1'부터 'code(2)10'까지 반복.
    위와 마찬가지로 값은 모두 없겠죠?


    세 번째 코드도 마찬가지입니다.
    불필요한 func_get_args() 사용, 맞지 않는 키(변수명).

    변수명에 대해서는 아래 페이지 설명 및 예제 읽어보세요.
    - http://php.net/manual/kr/language.variables.basics.php
    - http://php.net/manual/en/language.variables.basics.php


    변수가 'xxx_문자_문자_숫자' 형태면 거기에 맞게 표현되도록 해야죠.

    $loop = 2; // a, b → 2개
    for ($i=0;$i<$loop;$i++)
    {
        echo chr(97+$i).'<br />';
    }

    a
    b

    $loop = 3; // a, b, c → 3개
    for ($i=0;$i<$loop;$i++)
    {
        echo 'xxx_a_'.chr(97+$i).'<br />';
    }
    xxx_a_a
    xxx_a_b
    xxx_a_c

    위 코드를 기초로 살을 붙여가면 됩니다. 차근차근 해보세요.

+ 이름

- 홈페이지

+ 내용

+ 비밀번호

* 4~20자

+ CAPTCHA

CAPTCHA Image [새로고침] (대소문자 무시)

  • 번호

  • 제목

  • 이름

  • 등록일

  • 조회수