재미로 써보는 한 줄 Python

talpo의 이미지

아래와 같은 텍스트 데이터가 있습니다.

			4AEA, 4AF2, 4AFA, 4B03,
			4B0D, 4B16, 4B1E, 4B26,
			4B2F, 4B39, 4B45, 4B4F,
 
			4B59, 4B61, 4B69, 4B70,
			4B7A, 4B83, 4B8B, 4B95,
			4B9E, 4BA4, 4BB0, 4BB7,

이것을 아래와 같은 식으로 바꿔서 C소스에 붙여 넣으려고 합니다.
{19178, ""},
{19186, ""},
{19164, ""},


1. 먼저 python 프롬프트에서 데이터를 스트링으로 묶습니다.
s='''
			4AEA, 4AF2, 4AFA, 4B03,
			4B0D, 4B16, 4B1E, 4B26,
			4B2F, 4B39, 4B45, 4B4F,
 
			4B59, 4B61, 4B69, 4B70,
			4B7A, 4B83, 4B8B, 4B95,
			4B9E, 4BA4, 4BB0, 4BB7,
'''

2. 이제 쉼표를 기준으로 자릅니다.

s.split(',')

결과는 문자열로 구성된 리스트가 됩니다.
['\n\t\t\t4AEA', ' 4AF2', ' 4AFA', ' 4B03', '\n\t\t\t4B0D', ' 4B16', ' 4B1E', ' 4B26', '\n\t\t\t4B2F', ' 4B39', ' 4B45', ' 4B4F', '\n\n\t\t\t4B59', ' 4B61', ' 4B69', ' 4B70', '\n\t\t\t4B7A', ' 4B83', ' 4B8B', ' 4B95', '\n\t\t\t4B9E', ' 4BA4', ' 4BB0', ' 4BB7', '\n']

3. 각 문자열 원소의 앞뒤로 붙은 공백 문자들을 떼어 냅니다.

map(lambda x:x.strip(), s.split(','))

결과는 아래와 같습니다.
['4AEA', '4AF2', '4AFA', '4B03', '4B0D', '4B16', '4B1E', '4B26', '4B2F', '4B39', '4B45', '4B4F', '4B59', '4B61', '4B69', '4B70', '4B7A', '4B83', '4B8B', '4B95', '4B9E', '4BA4', '4BB0', '4BB7', '']

4. 리스트에서 마지막 원소만 떼어 봅시다.

map(lambda x:x.strip(), s.split(','))[:-1]

결과는 아래와 같습니다.
['4AEA', '4AF2', '4AFA', '4B03', '4B0D', '4B16', '4B1E', '4B26', '4B2F', '4B39', '4B45', '4B4F', '4B59', '4B61', '4B69', '4B70', '4B7A', '4B83', '4B8B', '4B95', '4B9E', '4BA4', '4BB0', '4BB7']

5. 16진수 문자열의 리스트인데 10진수의 리스트로 바꿉시다.

map(lambda x:int(x,16), map(lambda x:x.strip(), s.split(','))[:-1])

결과는 아래와 같습니다.
[19178, 19186, 19194, 19203, 19213, 19222, 19230, 19238, 19247, 19257, 19269, 19279, 19289, 19297, 19305, 19312, 19322, 19331, 19339, 19349, 19358, 19364, 19376, 19383]

6. 리스트의 정수형 원소마다 원하는 문자열 한 줄로 만듭니다.

map(lambda x:'{%d, ""},' % int(x,16), map(lambda x:x.strip(), s.split(','))[:-1])

결과는 아래와 같습니다.
['{19178, ""},', '{19186, ""},', '{19194, ""},', '{19203, ""},', '{19213, ""},', '{19222, ""},', '{19230, ""},', '{19238, ""},', '{19247, ""},', '{19257, ""},', '{19269, ""},', '{19279, ""},', '{19289, ""},', '{19297, ""},', '{19305, ""},', '{19312, ""},', '{19322, ""},', '{19331, ""},', '{19339, ""},', '{19349, ""},', '{19358, ""},', '{19364, ""},', '{19376, ""},', '{19383, ""},']

7. 문자열 원소로 된 리스트를 하나의 문자열로 만들면서 각 줄 사이에 개행문자를 넣습니다.

'\n'.join(map(lambda x:'{%d, ""},' % int(x,16), map(lambda x:x.strip(), s.split(','))[:-1]))

'{19178, ""},\n{19186, ""},\n{19194, ""},\n{19203, ""},\n{19213, ""},\n{19222, ""},\n{19230, ""},\n{19238, ""},\n{19247, ""},\n{19257, ""},\n{19269, ""},\n{19279, ""},\n{19289, ""},\n{19297, ""},\n{19305, ""},\n{19312, ""},\n{19322, ""},\n{19331, ""},\n{19339, ""},\n{19349, ""},\n{19358, ""},\n{19364, ""},\n{19376, ""},\n{19383, ""},'

8. 이제 출력하면 끝입니다.

print '\n'.join(map(lambda x:'{%d, ""},' % int(x,16), map(lambda x:x.strip(), s.split(','))[:-1]))

{19178, ""},
{19186, ""},
{19194, ""},
{19203, ""},
{19213, ""},
{19222, ""},
{19230, ""},
{19238, ""},
{19247, ""},
{19257, ""},
{19269, ""},
{19279, ""},
{19289, ""},
{19297, ""},
{19305, ""},
{19312, ""},
{19322, ""},
{19331, ""},
{19339, ""},
{19349, ""},
{19358, ""},
{19364, ""},
{19376, ""},
{19383, ""},

aero의 이미지

$s에 해당 문자열이 들어가 있으면

print map qq/{@{[hex $_]}, ""},\n/, $s =~ m/([0-9A-F]+)/g;

하면 됩니다.

$s =~ m/([0-9A-F]+)/g
는 정규식으로 문자열에서 16진수를 매칭합니다. g modifier를 사용하면 정규식 자체가 계속적으로 매치한 것을 리스트로 만들어 넘겨줍니다.

그러면 map으로 리스트를 하나씩 받아서 한 줄씩 원하는 스트링을 만들어서 그 리스트를 print에 넘겨줍니다.

찍으면 끝입니다.

결과는 같습니다. :)

raymundo의 이미지

@{[hex $_]}

위는 어떻게 해석해야 되는 건가요?

[hex $_] 요게 익명 리스트의 레퍼런스이고 그걸 다시 @{ } 로 둘러싸서 리스트를 만드는 건가요? 아니면 @{[ ]} 전체가 어떤 의미가 있습니까?

펄은 예나 지금이나 알쏭달쏭;;;

좋은 하루 되세요!

aero의 이미지

Perl에서는 " ", qq/ / 안에 변수(예: $scalar, @array ) 를 적어주면
보간(interpolation)해서 찍히는 건 아실겁니다.

@{[ ]}를 쓰는 테크닉은 " "안에 어떤 표현식이 들어가면 표현식의 결과가 아니라
각각의 변수가 보간될 것이기 때문에 보간이 일어나는 배열로 만들어주기 위해
어떤 대상을 [ ]로 감싸 익명배열(배열 레퍼런스)로 만들고 다시 @{ }로
디레퍼런스 해서 배열로 만드는 테크닉입니다.

이것은 어떤 하나의 값일 때 뿐만 아니라 어떤 리스트를 돌려주는 결과를 찍을때
@{[split ' ',$str]}

해시를 바로 찍어보고 싶을때
@{[%hash]}
이런식으로 다목적으로 사용가능합니다.

@{[ ]} 안은 list context라는 것을 이해하면 다양하게 응용할 수 있겠죠 :)

raymundo의 이미지

오오 그렇군요 감사합니다.

좋은 하루 되세요!

keedi의 이미지

perl 버전입니다. :-)

map {
    s/,$//;
    print qq|{@{[hex]}, ""},\n|
} @list = qw(
    4AEA, 4AF2, 4AFA, 4B03,
    4B0D, 4B16, 4B1E, 4B26,
    4B2F, 4B39, 4B45, 4B4F,
 
    4B59, 4B61, 4B69, 4B70,
    4B7A, 4B83, 4B8B, 4B95,
    4B9E, 4BA4, 4BB0, 4BB7,
);

---------------------------
Smashing Watermelons~!!
Whatever Nevermind~!!

Keedi Kim

----
use perl;

Keedi Kim

cedar의 이미지

Python 2.4 부터 지원하는 list comprehension이나 generator comprehension(가능한 한 이쪽)으로 바꿔쓰는 것을 추천합니다.

print ',\n'.join('{%d, ""}' % int(x.strip(), 16) for x in s.split(',') if x != '\n')

winner의 이미지

apply, coerce, intern이 deprecated 되었다는 글을 읽었지만
map은 잘 모르겠네요. 이유는 무엇인지도 궁금하고요.
제가 알기로는 Guido가 lambda도 싫어한다고 하는 것으로 아는데...

serialx의 이미지

1. 메모리 절약
2. 빠르다
3. 이해하기 좋다

정도일것 같네요 -_-a.

winner의 이미지

메모리 절약이라는 것은 map을 제거해서 Python 해석기를 가볍게 하고자 함인가요?
빠르다는 것의 근거는 뭐죠?
이해하기 좋다라... 함축(comprehension)이 마치 수학집한의 조건제시법과 유사하기 때문인가요?
map은 map을 알고 있는 사람한테는 무엇을 하고자 하는지 분명히 알 수 있다고 생각하는데
아닌가요?

Python 3.0에서는 map은 반복자를 반환하는 것으로 바뀐다고 언급하지
사라진다고 언급하지는 않습니다.

어디서 map을 제거하기로 했는지 확인을 하고 싶는데 link 부탁.

lifthrasiir의 이미지

반복자를 반환하는 함수는 2.x대에서 itertools.imap이었죠. 그래서 원래 함수는 사라지고 imap이 이름이 바뀌는 것으로 된다라고 할 수도 있겠습니다.

talpo의 이미지

늦은 변명이지만 생각대로 하면 되는 python을 자랑하려다 졸렬한 예제를 만들어 봤습니다. :)

cedar의 이미지

import re
print ',\n'.join('{%d, ""}' % int(x, 16) for x in re.findall(r'[0-9A-F]+', s))
lifthrasiir의 이미지

그냥 생각나는 대로 써 보니 이런 코드가 나오네요.

for i in map(lambda x:int(x.strip(),16), s.split(',')): print '{%d, ""},' % i

굳이 '\n'.join을 쓸 필요 없이 for 문을 쓰는 게 더 간단한 것 같습니다. 자료의 조작(이 경우 strip해서 10진수로 바꾸는 과정)은 list comprehension이나 뭐 그런 걸로 하는 게 편하고요. 펄의 경우에도 비슷한 얘기를 할 수 있겠습니다.

cedar의 이미지

어차피 talpo님의 의도는 함수형 프로그래밍을 이용한 one liner를 소개하는 것이었고요,
실제 현업에서 다른 프로그래머와 협업을 위해서는
명령형 프로그래밍으로 하는 편이 유지보수에 더 좋을 겁니다.

for x in s.split(','):
  try:
    print '{%d, ""},' % int(x.strip(), 16)
  except ValueError:
    continue

파이썬이나 펄에서 함수형 프로그래밍은 코드량을 줄일 수 있을 경우 가독성을 해치지 않는 범위에서 써야 되는 것이 좋다고 봅니다.
list comprehension 이나 generator expressions은 map/lambda 구문의 나쁜 가독성을 훨씬 좋게 해주므로 가능한 이쪽으로 바꿔서 써주는 것이 좋겠죠.

임창진의 이미지

-match option 을 주시고 아래 패턴을 적용합니다.

<A>=\{$1, ""\},\n

http://gema.sourceforge.net/new/index.shtml