10. 리스트의 활용




1 리스트 정렬하기


1-1 리스트의 sort 메소드

  • L.sort() 함수는 리스트 L 자체를 변경하며 리턴값을 반환하지 않는다.
In [3]:
L = [1, 5, 3, 9, 8, 4, 2]
print L.sort()
print L
None
[1, 2, 3, 4, 5, 8, 9]
  • 파이썬은 디폴트로 cmp(a, b) 내장 함수를 이용하여 정렬 방식을 결정한다.
  • cmp(a, b)
    • if a < b: return -1
    • if a > b: return 1
    • if a == b: return 0
In [45]:
print cmp(1,2)

print cmp(5,2)

print cmp('abc', 'abc')
-1
1
0
  • 기본 정렬 방식을 변경하려면 cmp(a, b)와 같은 비교 함수를 직접 만들어서 sort() 함수의 인자로 넣는다.
In [1]:
def mycmp(a1, a2): # 대소관계에 따른 순서를 반대로 바꾸었음
    return cmp(a2, a1)

L = [1, 5, 3, 2, 4, 6]
L.sort(mycmp) # 역순으로 정렬
print L
[6, 5, 4, 3, 2, 1]
  • 여러 튜플을 요소로 지닌 리스트인 경우, 튜플의 첫번째 값이 아닌 다른 위치에 있는 값을 기준으로 정렬
In [49]:
def cmp_1(a1, a2):
    return cmp(a1[1], a2[1])

def cmp_2(a1, a2):
    return cmp(a1[2], a2[2])

L = [ ('lee', 5, 38), ('kim', 3, 28), ('jung', 10, 36)]
L.sort()
print 'sorted by name:', L

L.sort(cmp_1)
print 'sorted by experience:', L

L.sort(cmp_2)
print 'sorted by age:', L
sorted by name: [('jung', 10, 36), ('kim', 3, 28), ('lee', 5, 38)]
sorted by experience: [('kim', 3, 28), ('lee', 5, 38), ('jung', 10, 36)]
sorted by age: [('kim', 3, 28), ('jung', 10, 36), ('lee', 5, 38)]
  • sort() 함수 인자로 reverse 값을 받을 수 있다.
    • 디폴트 reverse 인자값은 False
    • reverse 인자값을 True로 주면 역순으로 정렬됨
In [2]:
L = [1, 6, 3, 8, 6, 2, 9]
L.sort(reverse = True)
print L
[9, 8, 6, 6, 3, 2, 1]
  • sort() 함수 인자로 key에 함수를 넣어줄 수 있다.
    • key 인자에 함수가 할당되어 있으면 각 리스트 원소에 대해 비교함수 호출 직전에 key 함수를 먼저 호출한다.
In [51]:
L = ['123', '34', '56', '2345']
L.sort()
print L

L.sort(key=int)
print L
['123', '2345', '34', '56']
['34', '56', '123', '2345']

1-2 sorted 내장 함수

  • sorted() 내장함수는 L 자체에는 내용 변경 없이 정렬이 되어진 새로운 리스트를 반환한다.
In [15]:
L = [1, 6, 3, 8, 6, 2, 9]
newList = sorted(L)
print newList
print L
[1, 2, 3, 6, 6, 8, 9]
[1, 6, 3, 8, 6, 2, 9]
In [55]:
for ele in sorted(L):
    print ele,
1 2 3 6 6 8 9
  • sorted() 함수의 두번째 인자로 cmp 함수 지정 가능
In [10]:
def mycmp(a1, a2):      # 대소관계에 따른 순서를 반대로 바꾸었음
    return cmp(a2, a1)

L = [1, 5, 3, 2, 4, 6]
print sorted(L, mycmp)  # 역순으로 정렬
print L
[6, 5, 4, 3, 2, 1]
[1, 5, 3, 2, 4, 6]
  • 인자로 reverse와 key 지정 가능
In [9]:
L = [1, 6, 3, 8, 6, 2, 9]
print sorted(L, reverse=True)

L = ['123', '34', '56', '2345']
print sorted(L, key=int)
[9, 8, 6, 6, 3, 2, 1]
['34', '56', '123', '2345']

1-3 L.reverse() 와 reversed() 내장 함수

  • L.reverse()도 반환값이 없다.
    • 즉, L 자체를 역순으로 뒤집는다.
    • [주의] 역순 정렬이 아니다.
In [2]:
L = [1, 6, 3, 8, 6, 2, 9]
print L.reverse()
print L
None
[9, 2, 6, 8, 3, 6, 1]
In [27]:
L = [1, 6, 3, 8, 6, 2, 9]
L.reverse()       # 역순으로 뒤집는다.
for ele in L:
  print ele + 2,

print
L.reverse()       # 다시 원상태로 복귀시킨다.
print L
11 4 8 10 5 8 3
[1, 6, 3, 8, 6, 2, 9]
  • reversed() 내장함수는 sorted() 처럼 내용이 뒤집힌 리스트를 반환한다.
    • sorted() 처럼 원래 리스트 내용에는 변함없다.
In [31]:
L = [1, 6, 3, 8, 6, 2, 9]
print L
for ele in reversed(L):
    print ele + 2, 
print
print L
[1, 6, 3, 8, 6, 2, 9]
11 4 8 10 5 8 3
[1, 6, 3, 8, 6, 2, 9]

2 리스트 내포(List Comprehension)


  • 일반적인 리스트 생성법
In [74]:
L = []
for k in range(10):
    L.append(k*k)
    
print L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • 위 코딩은 리스트 내포 리터럴 방식을 활용해서 아래와 같이 변경할 수 있다.
In [32]:
L = [k * k for k in range(10)]
print L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • 리스트 내포 리터럴
    [expression for expr1 in sequence1
                for expr2 in sequence2 
                ...
                for exprN in sequenceN
                if condition]
    
  • expression의 평가 결과 반드시 한 개의 원소가 나와야 한다.
    • 틀린 예: [ x, y for x in seq1 for u in seq2 ]
  • 만약 두 개의 이상의 평가 결과가 나오면 튜플 등으로 감싸 주어야 한다.
    • 올바른 예: [ (x, y) for x in seq1 for u in seq2 ]
  • 위 리터럴은 다음의 일반적인 for 문의 리털러과 동일
    l = []
    for expr1 in sequence1:
      for expr2 in sequence2:
        ...
           for exprtN in sequenceN:
              if condition:
                 l.append(expression)
    
In [11]:
L = [k * k for k in range(10) if k % 2]   # 홀수의 제곱만 리스트로 형성
print L
[1, 9, 25, 49, 81]
  • 위의 리스트 내포 코드는 아래와 동일
In [2]:
L = []
for k in range(10):
    if k%2:
        L.append(k*k)
print L
[1, 9, 25, 49, 81]
  • 20보다 작은 2의 배수와 3의 배수에 대해 그 두 수의 합이 7의 배수인 것들에 대해 그 두 수의 곱을 출력하는 코드
In [5]:
L = [(i, j, i*j) for i in range(2, 20, 2) for j in range(3, 20, 3) if (i + j) % 7 == 0]
print L
[(2, 12, 24), (4, 3, 12), (6, 15, 90), (8, 6, 48), (10, 18, 180), (12, 9, 108), (16, 12, 192), (18, 3, 54)]
  • 두 개의 시퀀스 자료형에 대해 각각의 원소에 대한 쌍을 튜플 형태로 만들면서 리스트에 저장하는 코드
In [6]:
seq1 = 'abc'
seq2 = (1, 2, 3)
print [(x, y) for x in seq1 for y in seq2]
[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('b', 3), ('c', 1), ('c', 2), ('c', 3)]
In [2]:
words = 'The quick brown fox jumps over the lazy dog'.split()
stuff = [[w.upper(), w.lower(), len(w)] for w in words]
for i in stuff:
    print i
['THE', 'the', 3]
['QUICK', 'quick', 5]
['BROWN', 'brown', 5]
['FOX', 'fox', 3]
['JUMPS', 'jumps', 5]
['OVER', 'over', 4]
['THE', 'the', 3]
['LAZY', 'lazy', 4]
['DOG', 'dog', 3]

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일