221111_TIL

·2022년 11월 14일
0

Python

다룰 내용

  • 이중 for문
  • for문과 while문의 차이
  • for else문
  • List Comprehension (리스트 컴프리헨션)
  • range()
  • format()

이중 for문

  • 코드로 먼저 살펴보자
# 1~6 주사위 2개 모든 경우의 수 (36가지 경우의 수)
for j in range(1,7):
    for i in range(1,7):
        print(j,i)
    print()
    
#결과값    
1 1
1 2
1 3
1 4
1 5
1 6

2 1
2 2
2 3
2 4
2 5
2 6

3 1
3 2
3 3
3 4
3 5
3 6


4 1
4 2
4 3
4 4
4 5
4 6

5 1
5 2
5 3
5 4
5 5
5 6

6 1
6 2
6 3
6 4
6 5
6 6

2번 문제
# 구구단 전체
 for j in range(2,10): #2부터 9까지 숫자를 생성
     for i in range(1,10):
         print('{}*{}={}'.format(j,i,j*i))
     print()
#결과값
2*1=2
2*2=4
2*3=6
2*4=8
2*5=10
2*6=12
2*7=14
2*8=16
2*9=18

3*1=3
3*2=6
3*3=9
3*4=12
3*5=15
3*6=18
3*7=21
3*8=24
3*9=27

4*1=4
4*2=8
4*3=12
4*4=16
4*5=20
4*6=24
4*7=28
4*8=32
4*9=36

5*1=5
5*2=10
5*3=15
5*4=20
5*5=25
5*6=30
5*7=35
5*8=40
5*9=45

6*1=6
6*2=12
6*3=18
6*4=24
6*5=30
6*6=36
6*7=42
6*8=48
6*9=54

7*1=7
7*2=14
7*3=21
7*4=28
7*5=35
7*6=42
7*7=49
7*8=56
7*9=63

8*1=8
8*2=16
8*3=24
8*4=32
8*5=40
8*6=48
8*7=56
8*8=64
8*9=72

9*1=9
9*2=18
9*3=27
9*4=36
9*5=45
9*6=54
9*7=63
9*8=72
9*9=81
  • 1번문제 -> 첫 번째 for문인 j가 1일 때, 안에 있는 for문 i를 6번 돌고, 다시 빠져나와서 j가 2가 되면, 안에 있는 for문 i를 6번 돌고... 이중 for문 작동 메커니즘은 이 코드를 보고 대강 이해하면 될 듯 하다.

for문과 while문의 차이

for

  • 반복하는 횟수가 정해져있는 경우. 즉, 명확한 경우에 for 구문을 사용한다.
  • for문은 순서열의 처음부터 끝까지 반복한다.
  • 변수에 지정한 범위의 내용을 하나씩 순차적 대입
  • 문자열, 리스트, 튜플 요소를 순회하다가 더이상 순회할 것이 없다면 for문을 빠져나오거나, 순회를 끝내기 전에 return값이 나온다면 for문은 그대로 종료된다.
  • for문은 for (변수) in (문자열, 리스트, 튜플, 배열) 부분을 통해 새로운 변수를 만든다.
    - list, array같이 길이가 정해져 있는 값을 사용하기 위함.

while

while [조건문]:
[수행부분]

count = 0

while count <= 10: # 조건문
print("Count = ", count) #수행부분
count += 1

  • 얼마나 반복 수행해야 하는지 모를 때, 특정한 조건에 도달할 때 까지 계속해서 명령을 하고싶을 때는 while 구문을 사용한다.
  • 조건문이 True인 경우, 내부의 수행 부분을 진행하고, 조건문이 False인 경우, while문을 빠져나간다.
  • 강제로 while문을 빠져나가고 싶을 때는 break문을 사용한다.
    - while(조건문): 부분을 통해 변수의 True, False 여부를 판단할 뿐, 새로운 변수를 만들 수는 없음.
    - 사용자의 입력이나 특정한 값이 나올 때까지 지속적으로 반복할 때 사용. while문은 무한루프를 만들기 위해서도 사용한다.
    for문은 파이썬 환경에서 무한루프가 불가능.

for else문

  • for문과 같이 사용되는 else문은 for문이 break등으로 중간에 빠져나오지 않고 끝까지 실행되었을 경우, else문이 실행되는 방식으로 사용된다.
  • for - else는 True, False를 가려낼때 flag변수를 따로 사용하지 않고도 구현이 가능하여 다양하게 활용 가능한 문법이다.
for i in range(5):
    print(i, end=' ')
else:
    print("for문이 끝까지 실행됬습니다!")
 
 
 
 
for i in range(5):
    if i == 2:
        break
    print(i, end=' ')
else:
    print("for문이 끝까지 실행됬습니다!")
   
   
   결과
   0 1 2 3 4 for문이 끝까지 실행됬습니다!
   0 1
    참조 : [링크텍스트](https://cagongman.tistory.com/30)
    
   

List Comprehension (리스트 컴프리헨션)

  • "간결하고, 실용적이고, 직관적인 기능" 이라하는데, 이제 한 번 알아보자.
  • 리스트 컴프리헨션(List Comprehension)은 직관적으로 리스트를 생성하는 방법이다.
    - 대괄호 "[", , ,"]"로 감싸고 내부에 for문과 if문을 사용하여 반복하며 조건에 만족하는 것만 리스트로 생성할 수 있다.

    [ <표현식> for <변수명> in <시퀀스> if <조건>]

  • 리스트 컴프리헨션(List Comprehension)을 사용하는 이유는, 직관적이고 여러줄 쓸걸 한 줄에 만들어 주기 때문이다.
  • 사용법
#리스트 컴프리헨션을 이용하여 0~4 리스트 만들기
[i for i in range(5)]

#일반적인 리스트 생성
li=[]
for i in range(5):
    li.append(i)

[참조](https://bio-info.tistory.com/28)

range()

  • range(10)은 0,1,2,3,4,5,6,7,8,9 숫자를 생성한다. range(stop) * 마지막 숫자는 생성하지 않음

  • range(start, stop)
    ㄴ 구구단 3단 코드를 구현해보면,

    for i in range(1,10): #1부터 9까지 숫자를 생성. (마지막 숫자는 생성하지 않으니까. 무조건 -1해서 생성한다고 생각하자.)
    print('{}{}={}'.format(3,i,3i))

    3*1 ~ 3*9의 값을 반환함.
    인자를 두 개 전달하는 경우, 첫 번째 인자는 시작하는 숫자가 된다.
  • range(start, stop, step)
    list(range(0, 10, 2)) >> 마지막 인자 step은 숫자의 간격을 나타낸다. 따라서 해당 코드는

    list(range(0, 10, 2)) --> [0,2,4,6,8]
    마지막 숫자는 생성하지 않음. 8까지 결과가 나온다.

  • step으로 음수를 지정할 수도 있음. (숫자 증가, 감소 둘 다 가능)

  • range()함수의 결과는 반복가능하기 때문에, for문을 사용하여 출력할 수 있음.

format()

  • format 함수는 중괄호 {, } 안에 포매팅을 지정하고 format 함수의 인자로 값들을 넣습니다.
    아래를 보면 한번에 느낌이 오실겁니다.

'{인덱스0}, {인덱스1}'.format(값0, 값1)
실제로 한번 볼까요? 구구단을 예로 들어보겠습니다.
1
2
3
4
5

a = 2
b = 3
s = '구구단 {0} x {1} = {2}'.format(a, b, a * b)
print(s)


문자열 '구구단 {0} x {1} = {2}' 를 보면 중괄호를 이용해서 format 함수에서 넣어줄 것들을 표기 해줍니다.
인덱스는 0 부터 시작합니다. 이렇게 표시를 해주고 .format 함수의 인자로 순서대로 넣을 변수들을 지정해 줍니다.
참조

#구구단 코드
for j in range(2,10): #2부터 9까지 숫자를 생성
    for i in range(1,10):
        print('{}*{}={}'.format(j,i,j*i))
    print() << 마지막 print()는 공백 추가.
    format()함수는 저렇게 중괄호 안에 어떤 것이 들어갈지 정해주면 사용가능.

Algorithm

# Linked List
# [3] -> [4]
# data, next
class Node:
    def __init__(self, data):  # class의 생성자에 data를 받는다. << 여기서의 data == parameter
        self.data = data  # 생성자에 받은 data를 self.data에 저장한다. << 여기서의 data == 클래스 내부에서 사용되는 저장되는 변수
        self.next = None
        # 처음 생성할 때는 [3] 이런 식으로 노드가 생성된다. 그래서 다음 노드를 가리키지 않기 때문에 포인터가 아무것도 가르키지 않는 다는 것을 None으로 표현.


# 3을 가진 Node를 만드려면 아래와 같이 하면 된다.
node = Node(3)  # 현재는 next가 없이 하나의 노드만 있다. [3]
first_node = Node(4)
node.next = first_node
print(node.next.data)
print(node.data)



class LinkedList: # 가지고 있을 데이터는 head node만 가지고 있으면 된다.
    def __init__(self,data): # LinkedList의 생성자
        self.head = Node(data) # 앞서 만든 class인 Node()를 불러옴.
# linked List 맨 뒤에 새로운 원소를 추가해보는 코드
    def append(self,data):
        if self.head is None:
            self.head = Node(data)
            return

        # self.head.next = Node(data) # head에다가 계속 다음 거에만 붙혀주고 있는 것.
        curr = self.head # curr에 맨 처음 노드 즉, head 를 넣어줌.
        while curr.next is not None:
            curr = curr.next
            print("curr is", curr.data)
        curr.next = Node(data)


    def print_all(self):
        print("hell")
        curr = self.head
        while curr is not None: # curr이 0(None)이 아닐때 까지 돌아라
            print(curr.data)
            curr = curr.next
# [3] -> [4] -> [5] -> [6] -> None

linked_list = LinkedList(3) # __init__(3)를 넣어줌
linked_list.append(4)
linked_list.append(5)
linked_list.print_all()
# print(linked_list.head.next) #LinkedList안에 self.head에 5를 주고, 5가 다시 Node(5)로 들어가서 Node클래스에 data 5로 들어감.


# 링스크 리스트 원소 찾기
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class LinkedList:
    def __init__(self, value):
        self.head = Node(value)

    def append(self, value):
        cur = self.head
        while cur.next is not None:
            cur = cur.next
        cur.next = Node(value)

    def print_all(self):
        cur = self.head
        while cur is not None:
            print(cur.data)
            cur = cur.next

    def get_node(self, index):
        node = self.head
        count = 0
        while count < index:
            node = node.next
            count += 1
        return node


linked_list = LinkedList(5)
linked_list.append(12)
print(linked_list.get_node(1).data)# -> 5를 들고 있는 노드를 반환해야 합니다!


# 리스트 원소 추가하기

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class LinkedList:
    def __init__(self, value):
        self.head = Node(value)

    def append(self, value):
        cur = self.head
        while cur.next is not None:
            cur = cur.next
        cur.next = Node(value)

    def print_all(self):
        cur = self.head
        while cur is not None:
            print(cur.data)
            cur = cur.next

    def get_node(self, index):
        node = self.head
        count = 0
        while count < index:
            node = node.next
            count += 1
        return node



    #   index        next_node
    #  ['자갈']       ['밀가루']->['우편']
    #          new_node
    #       ->  ['흑연'] ->
    # index.next = new_node <<  head node인 index의 다음인 index.next는 new_node에 포인터를 연결
    # new_node.next = next_node << 새롭게 추가될 new_node의 다음인 new_node.next는 next_node에 연결
    def add_node(self,index:int,value:int):
        new_node = Node(value) # 밑에 linked_list.add_node(1, 6) 이 코드 때문에 현재 value값은 [6]
        # node = self.get_node(index - 1) << 0번째 노드를 잡아오기 위해 index - 1을 해줌. 여기서 값은 밑에 linked_list = LinkedList(5)때문에 0번째 index가 [5]임. 따라서 [5]를 집어올 것임.
        node = self.get_node(index - 1)   # 클래스 내부에 있는 다른 함수를 부르기 위해서는 self.그 함수 이름을 호출하면 된다. << 이렇게 클래스 내에 있는 함수를 호출할 수 있게 된다.
        next_node = node.next # 현재 5의 다음 것(== node.next)인 [12] (== next_node)
        node.next = new_node # 5 다음을 6으로 만듦.?? (node.next는 위에서 12를 받았는데, 왜 5 다음을 6으로 만든것인가?)
        # ㄴ node.next가 기존에 12를 가리키고 있었던 것을 새로운 노드인 6에 연결하게끔 값을 넣어줌. (오늘쪽 값을 왼쪽에 대입 !)
        new_node.next = next_node # 새로운 노드는 새로운 노드의 다음과 똑같음.




        return

# [5] -> [12]
linked_list = LinkedList(5)
linked_list.append(12)
linked_list.append(8)

# [5] -> [12] -> [8]
# [5] -> [6] -> [12] -> [8]
# add_node메소드의 (index - 1) 덕분에 add_node(1, 6)을 넣으면 0번째인 [5]가 들어있는 노드를 잡을 수 있음.
linked_list.add_node(1, 6) # << [5] -> [12]node, 1번째 index -> [6] -> [8] // 5 - 12 - 6 -8
# linked_list.add_node(0, 6) # << [5]node, 0번째 index -> [6] -> [12] -> [8] // 5 - 6 - 12 -8
linked_list.print_all()
  • class Node안에 있는 메소드들의 self는 class Node(data)를 가리키고 있음.
  • Linked List의 포인터는 '끊고 새로 연결한다'라는 사고를 가지고 접근해야 한다.
  • 아래 코드 부분이 제일 헷갈렸었음. (노드를 중간에 추가했기 때문에 기존 포인터들을 끊고 새로 연결해야하는 코드.)
new_node는 6. 그리고 new_node = Node(value) << class Node의 함수임.
#   index        next_node
    #  ['자갈']       ['밀가루']->['우편']
    #          new_node
    #       ->  ['흑연'] ->
    # index.next = new_node <<  head node인 index의 다음인 index.next는 new_node에 포인터를 연결
    # new_node.next = next_node << 새롭게 추가될 new_node의 다음인 new_node.next는 next_node에 연결
    def add_node(self,index:int,value:int):
        new_node = Node(value) # 밑에 linked_list.add_node(1, 6) 이 코드 때문에 현재 value값은 [6]
        # node = self.get_node(index - 1) << 0번째 노드를 잡아오기 위해 index - 1을 해줌. 여기서 값은 밑에 linked_list = LinkedList(5)때문에 0번째 index가 [5]임. 따라서 [5]를 집어올 것임.
        node = self.get_node(index - 1)   # 클래스 내부에 있는 다른 함수를 부르기 위해서는 self.그 함수 이름을 호출하면 된다. << 이렇게 클래스 내에 있는 함수를 호출할 수 있게 된다.
        next_node = node.next # 현재 5의 다음 것(== node.next)인 [12] (== next_node)
        node.next = new_node # 5 다음을 6으로 만듦.?? (node.next는 위에서 12를 받았는데, 왜 5 다음을 6으로 만든것인가?)
        # ㄴ node.next가 기존에 12를 가리키고 있었던 것을 새로운 노드인 6에 연결하게끔 값을 넣어줌. (오늘쪽 값을 왼쪽에 대입 !)
        new_node.next = next_node # 새로운 노드는 새로운 노드의 다음과 똑같음.

Javascript

헷갈렸던 내용

  • 연산자
    - / << int 나누기 (https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Division)
    - % << 나눈 뒤, 몫을 구할 때 사용
    - 어떤 변수에 값을 할당할 때, 무조건 오른쪽 값을 왼쪽에 할당 ==> Python과 공통 내용
    • 예시 ) node.next = new_node
      node.next에 new_node의 값을 할당해줌.
      즉, 기존 node.next값에 new_node 값을 덮어씌움

0개의 댓글