ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] list, tuple, dictionary, iterator(map, filter)
    💫 Computer Science/Python & AI Framework 2020. 9. 6. 00:44

     

    알고리즘 문제를 푸는데 자꾸 헷갈리는 파이썬 개념과 메소드들을 정리하려고 한다.

     

    파이썬 자료형 종류와 차이점 - 리스트, 튜플, 딕셔너리

     

    • 리스트
    a = [1,2,3,4]
    b = [1,2,[a,b]]

    변수를 여러개 저장할 수 있는 자료구조 중 대표적인 것. 반복문을 통해 데이터 관리가 가능하고 다양한 모양으로 생성할 수 있다. 정수와 문자를 섞어 넣는다던지, 리스트 안에 리스트를 넣는다던지

     

    • 튜플
    a = (1,2,3)
    b = (1,)
    c = 1,2,3
    d = ('a','b',('c','d'))

    리스트와 거의 유사하나 차이점은

    1개의 요소만을 가질 때 반드시 , 붙여주어야 하고 괄호 생략해도 무방하다는 점 또, 요소의 값을 변경하거나 지울 수 없다. 대신 리스트보다 빠르다. 수정할 필요가 없는 리스트는 튜플로 작성해도 괜찮지만 리스트나 딕셔너리보다 잘 사용하지 않는 것 같다.

     

    • 딕셔너리
    a = {'a': 1, 'b': 2}
    b = {'a':[1,2,3], 'b':[4]}
    a[a] # 1
    b[a] # [1,2,3]

    키-쌍 값으로 이루어진 자료구조. 키를 가지고 바로 값을 찾을 수 있어 리스트의 요소의 개수가 많을 때 탐색이 필요하다면 리스트보다 딕셔너리가 훨씬 빠를 수 있다. 대신 인덱스로 접근 할 수 없고 키 값으로만 접근 가능.

     

     


     

     

    1. 리스트 사용하기

     

    - 리스트 조작 메서드 : append, extend, insert

     

    a = [1,2,3,6]
    a.append(4) # [1,2,3,6,4]

    append는 리스트 끝에 요소 하나를 추가

     

    a = [1,2,3,4]
    a.append([100,200]) # [1,2,3,4,[100,200]]
    len(a) # 5

    리스트를 append하면 리스트 안에 리스트가 들어가 중첩리스트가 만들어진다. 추가한 1개의 리스트가 1개의 요소이기 때문에 길이는 4+1인 5이다.

     

    a = [1,2,3,4]
    a.extend([100,200]) # [1,2,3,4,100,200]
    len(a) # 6

    요소를 여러개 추가 하고 싶으면 extend를 사용한다. 리스트끼리 연결을 하는 것이다.

     

    a = [1,2,3,4]
    a.insert(2, 100) # [1,2,100,3,4]

    insert(인덱스, 요소)  파라미터로 준 인덱스 자리에 요소를 추가하고 뒤로 민다.

     


     

    - 리스트 삭제 메서드 : pop, del, remove

     

    a = [1,2,3,4]
    a.pop() # [1,2,3]
    n = a.pop(0) 
    print(a) # [2,3]
    print(n) # 1

    pop()은 파라미터를 지정해주지 않으면 맨 뒤의 요소를 삭제하고 파라미터로 인덱스를 지정해주면 해당 인덱스 요소가 삭제되고 pop한 값을 변수에 넣어 줄 수 있다. DFS, BFS 문제에서 많이 사용한다.

     

    a = [1,2,3,4]
    del a[1] # [1,3,4]

    del과 pop은 비슷하게 동작하나, 지운 리스트 내 요소 값을 따로 사용할 때는 pop()을 사용한다.

     

    a = [10,20,30,40,20]
    a.remove(20) # [10,30,40,20]

    인덱스 말고 원하는 값을 삭제하고 싶을 때는 remove를 사용합니다. 만약 그 값이 여러개라면 처음 값만 삭제함.

     

     

     

    ※ 참고 deque(덱) 객체

    from collections import deque
    
    q = deque([[1,[1]]])
    print(q)
    q.append([2,[1,2]])
    print(q)
    
    qq = deque([1])
    print(qq)
    qq.append(1)
    print(qq)
    
    deque([[1, [1]]])
    deque([[1, [1]], [2, [1, 2]]])
    deque([1])
    deque([1, 1])

    리스트로 스택과 큐 만들기는 이전 포스팅 참고

     

     


    - 리스트 슬라이싱[:]

     

    a = [1,2,3,4,5,6,7]
    print(a[:3]) # [1,2,3]
    print(a[2:]) # [3,4,5,6,7]
    print(a[3:5] # [4,5]
    print(a[-1]) # 7

    리스트명[시작인덱스:끝인덱스] 로 지정해 슬라이싱을 할 수 있고 이렇게 지정하게 되면 (시작인덱스)~(끝인덱스-1)한 값까지 출력됩니다. 인덱스가 -1이란 것은 리스트의 가장 끝 값을 말합니다.

     

     


     

    - 기타 메소드

    .index(값) : 리스트 안의 값에 해당하는 인덱스를 구한다.

    .count(값) : 리스트 안의 값에 해당하는 개수를 구한다.

    .reverse() : 리스트 요소의 순서를 반대로 뒤집는다.

    .sort() : 리스트의 요소를 정렬, 내림차순으로 정렬하려면 .sort(reverse=True)

    .sorted() : sort()와 동일하나 기존의 리스트는 그대로 두고 새 리스트에 정렬한 리스트를 반환

    .clear(): del a[:]와 같고 리스트의 모든 요소를 삭제한다.

    if not 리스트, if 리스트 : 리스트가 비어있는지 조건 확인할 때.

     


    - 2차원 리스트 초기화

    # 2*5리스트 만들기 2행 5열
    lis = [[0]*5 for _ in range(2)]
    print(lis)
    # [[0,0,0,0,0],[0,0,0,0,0]]
    
    liss = [[i for i in range(3)] for _ in range(3)]
    print(liss)
    # [[0,1,2],[0,1,2],[0,1,2]]
    
    lisss = [[0] * i for i in [3, 1, 3, 2, 5]]
    print(lisss)
    # [[0, 0, 0], [0], [0, 0, 0], [0, 0], [0, 0, 0, 0, 0]]

     

    - 2차원 리스트 출력

    lis = [[i,i+1] for i in range(3)]
    print(lis)
    # [[0, 1], [1, 2], [2, 3]]
    for x, y in lis:
    	print(x,y)
    # 0 1
    # 1 2
    # 2 3

    - 리스트 중복 제거

    lis = [1,1,2,3,3,4,4]
    lis = list(set(lis)) # [1,2,3,4]

    set으로 변환 후 다시 리스트로 변환 하면 되는데, 순서가 뒤죽박죽 된다는 단점이 있다.

     

    순서를 지켜주려면 for 문을 이용해야 한다.

    lis = [1,1,2,3,3,4,4]
    new_lis = []
    for li in lis:
        if li not in new_lis:
            new_lis.append(li)
    print(new_lis)

     


    2. 딕셔너리 사용하기

     

    - 딕셔너리 조작 메서드 : setdefault, update, pop

     

    d = {'a': 'aa', 'b': 'bb'}
    print(d[a])
    # aa
    
    dd = {i:[i+1,i+2] for i in range(3)
    print(d)
    # {0:[1,2], 1:[2,3], 2:[3,4]}

    이런 식으로 값을 직접 넣어 딕셔너리를 초기화 할 수도 있지만, (딕셔너리는 append X)

     

    x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
    x.setdefault('e')
    print(x)
    # {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None}
    
    x.setdefault('f',100)
    print(x)
    # {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': None, 'f':100}

    setdefault메소드를 이용할 수도 있습니다. 파미터에 키, 값 순서대로 넣어주면 되는데 만약 값을 지정해주지 않으면 키만 저장하고 값에 None을 저장합니다.

     

    x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
    x.update(a=100, d=400)
    print(x)
    # {'a': 100, 'b': 20, 'c': 30, 'd': 400}
    
    y = {1: 10, 2: 20, 3: 30, 4: 40}
    y.update({1:100, 3:300})
    print(y)
    # {1: 100, 2: 20, 3: 300, 4: 40}
    
    y.update([[2,200], [4,400])
    # # {1: 100, 2: 200, 3: 300, 4: 400}

    .update는 값을 수정하고 싶을 때 사용하고 키=값을 파라미터로 넣어주면됩니다. 대신 이는 키 값이 문자열일 때만 가능하며 키가 숫자일 때는 update(딕셔너리)를 사용합니다. 또는 [[]]를 이용해 [[키1,값1],...]형식으로 update할 수도 있습니다.

     

    setdefault와 update의 차이점은 setdefault는 이미 들어간 키 값의 수정이 불가능 하지만 update는 가능합니다.

     

    x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
    del x['a']
    x.pop('b')
    print(x)
    # {'c': 30, 'd': 40}

    pop과 del은 리스트에서의 사용법과 동일하고, .clear(모든요소삭제)도 동일합니다.

     

     

     

    - 그 외 메서드

     x = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
     
     # 키 값 가져오기
     print(x.get('a')) # 10
     
     # 키 값 모두 가져오기
     print(x.items()) # dict_items([('a', 10), ('b', 20), ('c', 30), ('d', 40)])
     
     # 키 값 모두
     print(x.keys())
     
     # value 값 모두
     print(x.values())

     

     


     

     

    3. iteroator를 결과값으로 리턴해주는 내장함수

     

     

    - map : 반복가능한(iterable) 객체를 받아 각 요소에 함수를 적용해주는 함수이다.

     

    map(적용시킬 함수, 적용시킬 요소)

     

    def add(n):
    	return n+1
    
    a = ['1','2','3','4']
    result = map(int, a)
    result2 = map(add, a)
    
    print(result) # [1,2,3,4]
    print(result2) # [2,3,4,5]

     


     

    - filter : 특정 조건으로 걸러서 걸러진 요소들로 iterator 객체를 만들어 리턴

     

    filter(적용시킬 함수, 적용시킬 요소)

     

    target = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    result = []
    
    def is_even(n):
          return True if n % 2 == 0 else False
    
    for value in target:
         if is_even(value):
            result.append(value)
    
    print(result)  # [2, 4, 6, 8, 10]

     


     

    4. 리스트에 map 사용하기

     

    a = [1.2, 2.5, 3.7, 4.6]
    
    # map 객체 생성
    a = map(int, a)
    print(a) # <map object at 0x000001A65414B3A0> 
    
    b = list(map(int, a))
    print(b) # [1,2,3,4]
    
    c = input().split()
    # 10 20 (입력)
    print(c) # ['10', '20']
    
    d = map(int, input().split())
    # 10 20 (입력)
    print(d) # <map object at 0x03DFB0D0>
    print(list(d)) # [10, 20]
    
    a, b = [10, 20]
    print(a, b) # 10 20
    
    c, d = map(int, input().split())
    # 10 20 (입력)
    print(c, d) # 10 20

    d = map(int, input().split()) 로 여러개의 값을 띄어쓰기로 입력 받으면(예를 들어 1 2 3 을 입력했다고 하면) 1 2 3이 들어있는 맵 객체가 d에 들어가고 그대로 출력하게되면 d에 있는 맵 객체의 주소가 출력되고 안의 값을 볼 수 없습니다.

     

    하지만 맵 객체는 iterator 이기 때문에 unpacking(언패킹)이 가능합니다. a,b = [1,2] 로 지정하면 a=1, b=2가 되는 것 처럼 안의 요소들을 각각의 변수로 저장하는 것을 언패킹이라고 합니다.

     

    따라서 a, b = map(int, input().split())으로 지정하면 맵 객체가 반환되는 것이 아니라 각각 언패킹 된 개별의 값이 a와 b에 저장됩니다.

     

     

     


    5. 파이썬으로 입력받기 sys.stdin

     

    알고리즘 문제를 풀다보면 입력 값을 input().split()으로 많이 받게 되는데,

    그냥 input()과, raw_input()은 파이썬의 sys.stdin으로 입력받는 방법보다 느리다.

     

    a = sys.stdin
    # ^Z를 입력. 받을 때까지 입력을 받는다. stdin 오브젝트로 반환
    
    a = sys.stdin.readline()
    # 한 줄 입력. 가장 많이 사용. \n(개행문자)이 붙는다.
    
    a = sys.stdin.readline().strip()
    # \n(개행문자) 자동 삭제
    
    a,b = sys.stdin.readline().split()
    # 알고리즘 문제 풀 때 많이 사용하는 방법 띄어쓰기 기준으로 나눔

     

     

     

    다음 포스팅에서는 문자열을 다루는 방법(strip, replace...등)에 대해서 다룰 예정이다.

    댓글

Designed by Tistory.