[PHP] 코드 줄이기 > 강의

본문 바로가기
사이트 내 전체검색

강의

[PHP] 코드 줄이기

페이지 정보

작성자 BiHon 댓글 4건 조회 3,307회 작성일 12-11-05 20:12

본문

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개

댓글목록

멍우연님의 댓글

멍우연 작성일

잉...  배열 이용해서 function 만들고 for문 돌리고 func_get_args()도 써봤는데...

논리오류만 나네요... ㅜ ㅜ      계속 아무런 값도 안나오네요.. 흑흑...

BiHon님의 댓글

BiHon 작성일

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

차근차근 해보세요.

멍우연님의 댓글

멍우연 작성일

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 값 뜨는지 공백표시 되네요 ㅎㅎ;

BiHon님의 댓글

BiHon 작성일

박수!



소스 상단에 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



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

회원로그인


Copyright © 1998~2019 DreamPHP.com All rights reserved.