반응형
반응형

nullish 병합 연산자

nullish 병합 연산자(nullish coalescing operator)

 

https://ko.javascript.info/nullish-coalescing-operator#ref-778

 

nullish 병합 연산자 '??'

 

ko.javascript.info

 

nullish 병합 연산자(nullish coalescing operator) ??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 ‘확정되어있는’ 변수를 찾을 수 있습니다.

a ?? b의 평가 결과는 다음과 같습니다.

  • a가 null도 아니고 undefined도 아니면 a
  • 그 외의 경우는 b

nullish 병합 연산자 ??없이 x = a ?? b와 동일한 동작을 하는 코드를 작성하면 다음과 같습니다.

x = (a !== null && a !== undefined) ? a : b;

비교 연산자와 논리 연산자만으로 nullish 병합 연산자와 같은 기능을 하는 코드를 작성하니 코드 길이가 길어지네요.

또 다른 예시를 살펴봅시다. firstName, lastName, nickName이란 변수에 사용자 이름이나 별명을 저장하는데, 사용자가 아무런 정보도 입력하지 않는 케이스도 허용한다고 해보겠습니다.

화면엔 세 변수 중 실제 값이 있는 변수의 값을 출력하는데, 세 변수 모두 값이 없다면 '익명의 사용자’가 출력되도록 해보죠.

이럴 때 nullish 병합 연산자 ??를 사용하면 값이 정해진 변수를 간편하게 찾아낼 수 있습니다.

 
 
let firstName = null;
let lastName = null;
let nickName = "바이올렛";

// null이나 undefined가 아닌 첫 번째 피연산자
alert(firstName ?? lastName ?? nickName ?? "익명의 사용자"); // 바이올렛

'??'와 '||'의 차이

nullish 병합 연산자는 OR 연산자 ||와 상당히 유사해 보입니다. 실제로 위 예시에서 ??를 ||로 바꿔도 그 결과는 동일하기까지 하죠. 관련 내용은 이전 챕터에서 살펴본 바 있습니다.

그런데 두 연산자 사이에는 중요한 차이점이 있습니다.

  • ||는 첫 번째 truthy 값을 반환합니다.
  • ??는 첫 번째 정의된(defined) 값을 반환합니다.

null과 undefined, 숫자 0을 구분 지어 다뤄야 할 때 이 차이점은 매우 중요한 역할을 합니다.

예시를 살펴봅시다.

height = height ?? 100;

height에 값이 정의되지 않은경우 height엔 100이 할당됩니다.

이제 ??와 ||을 비교해봅시다.

 
 
let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0

height || 100은 height에 0을 할당했지만 0을 falsy 한 값으로 취급했기 때문에 null이나 undefined를 할당한 것과 동일하게 처리합니다. 따라서 height || 100의 평가 결과는 100입니다.

반면 height ?? 100의 평가 결과는 height가 정확하게 null이나 undefined일 경우에만 100이 됩니다. 예시에선 height에 0이라는 값을 할당했기 때문에 얼럿창엔 0이 출력됩니다.

이런 특징 때문에 높이처럼 0이 할당될 수 있는 변수를 사용해 기능을 개발할 땐 ||보다 ??가 적합합니다.

연산자 우선순위

??의 연산자 우선순위 5로 꽤 낮습니다.

따라서 ??는 =와 ? 보다는 먼저, 대부분의 연산자보다는 나중에 평가됩니다.

그렇기 때문에 복잡한 표현식 안에서 ??를 사용해 값을 하나 선택할 땐 괄호를 추가하는 게 좋습니다.

 
 
let height = null;
let width = null;

// 괄호를 추가!
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000

그렇지 않으면 *가 ??보다 우선순위가 높기 때문에 *가 먼저 실행됩니다.

결국엔 아래 예시처럼 동작하겠죠.

// 원치 않는 결과
let area = height ?? (100 * width) ?? 50;

??엔 자바스크립트 언어에서 규정한 또 다른 제약사항이 있습니다.

안정성 관련 이슈 때문에 ??는 &&나 ||와 함께 사용하지 못합니다.

아래 예시를 실행하면 문법 에러가 발생합니다.

 
 
let x = 1 && 2 ?? 3; // SyntaxError: Unexpected token '??'

이 제약에 대해선 아직 논쟁이 많긴 하지만 사람들이 ||를 ??로 바꾸기 시작하면서 만드는 실수를 방지하고자 명세서에 제약이 추가된 상황입니다.

제약을 피하려면 괄호를 사용해주세요.

 
 
let x = (1 && 2) ?? 3; // 제대로 동작합니다.

alert(x); // 2

요약

  • nullish 병합 연산자 ??를 사용하면 피연산자 중 ‘값이 할당된’ 변수를 빠르게 찾을 수 있습니다.
    // height가 null이나 undefined인 경우, 100을 할당
    height = height ?? 100;
  • ??는 변수에 기본값을 할당하는 용도로 사용할 수 있습니다.
  • ??의 연산자 우선순위는 대다수의 연산자보다 낮고 ?와 = 보다는 높습니다.
  • 괄호 없이 ??를 ||나 &&와 함께 사용하는 것은 금지되어있습니다.
반응형
반응형

머스크 전기에 등장하는, 그의 ‘알고리즘’ 몇 가지를 소개해 드리려고 합니다. 다 쓰면 출판사에서 싫어할 것 같아서(물론 이 글은 광고가 아닙니다민!) 몇 개만 추려 볼게요. 

머스크의 알고리즘

모든 요구사항에 의문을 제기한다
부품이든 프로세스든 가능한 한 최대한 제거하라
단순화하고 최적화하라


머스크가 게임에서 배운 인생의 법칙

공감은 자산이 아니다
인생을 게임처럼 플레이하라
패배를 두려워하지 마라
상황을 주도하라

반응형
반응형

[python] pdf to png, 해상도 높게 저장하기 

 

import fitz  # PyMuPDF

def pdf_to_png(pdf_file, output_folder, dpi=300):
    # Open the PDF file
    pdf_document = fitz.open(pdf_file)
    
    for page_number in range(pdf_document.page_count):
        # Get the page
        page = pdf_document[page_number]
        
        # Set the resolution (DPI)
        zoom = dpi / 72.0
        mat = fitz.Matrix(zoom, zoom)
        image = page.get_pixmap(matrix=mat)
        
        # Save the image as a PNG file
        image.save(f"{output_folder}/page_{page_number + 1}.png", "png")

    # Close the PDF file
    pdf_document.close()

if __name__ == "__main__":
    input_pdf = "input.pdf"  # Replace with your PDF file path
    output_folder = "output_images"  # Replace with your output folder
    dpi = 600  # Adjust DPI as needed
    
    pdf_to_png(input_pdf, output_folder, dpi)
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[python] PyAudio  (0) 2023.10.20
[Python] savefig 0.0.4  (0) 2023.10.17
[python] matrix 3.0.0  (0) 2023.10.04
[python] 알고리즘 - 탐색  (0) 2023.09.27
[python] 알고리즘 - 정렬  (0) 2023.09.27
반응형

https://pypi.org/project/matrix/

 

matrix

Generic matrix generator.

pypi.org

matrix 3.0.0

Generic matrix generator.

Installation

pip install matrix

You can also install the in-development version with:

pip install https://github.com/ionelmc/python-matrix/archive/main.zip

Documentation

https://python-matrix.readthedocs.io/

Development

To run all the tests run:

tox
반응형
반응형

알고리즘 탐색(Search)

탐색이란, 원하는 값을 찾는 것입니다.

선형 탐색(Linear Search)

순서대로 하나씩 찾는 방법 입니다.

이분(이진) 탐색(Binary Search)

반씩 제외하면서 찾는 방법 입니다.

해시 탐색(Hash Search)

선형탐색이나 이진탐색은, 어떤 값이 어떤 index에 들어있는지에 대한 정보가 없는 상태에서 탐색할 때 사용하는 방식이 었습니다.반면에 해시 탐색은 값과 index를 미리 연결해 둠으로써 짧은 시간에 탐색할 수 있는 알고리즘입니다.

완전 탐색

브루트 포스(Brute Force)

brute: 무식한, force: 힘 무식한 힘으로 해석할 수 있다. 완전탐색 알고리즘. 즉, 가능한 모든 경우의 수를 모두 탐색하면서 요구조건에 충족되는 결과만을 가져옵니다. 이 알고리즘의 강력한 점은 예외 없이 100%의 확률로 정답만을 출력한다는 점입니다.

백트래킹

해를 찾는 도중 해가 아니어서 막히면, 되돌아가서 다시 해를 찾아가는 기법을 말합니다. 최적화 문제와 결정 문제를 푸는 방법이 됩니다.

재귀함수

함수는 자기 자신을 내부에서 호출할 수 있다. 이러한 함수를 재귀 함수라고 한다. 재귀 알고리즘(recursive algorithm)이란 재귀 함수를 이용하여 문제를 해결하는 알고리즘을 말합니다.

# 정렬/탐색 알고리즘 : https://modulabs.co.kr/blog/algorithm-python/
# Search 탐색 

def linear_search(list, target):
    for i in range(0, len(list)):
        if list[i] == target:
            return i
    return None

def binary_search(list, target):
    first = 0
    last = len(list) - 1

    while first <= last:
        midpoint = (first + last) // 2
        if list[midpoint] == target:
            return midpoint
        elif list[midpoint] < target:
            first = midpoint + 1
        else:
            last = midpoint - 1
    return None

def hash_search(list, target):
    hash_table = {}
    for i in range(0, len(list)):
        hash_table[list[i]] = i
    if target in hash_table:
        return hash_table[target]
    return None

def brute_force_search(list, target):
    for i in range(0, len(list)):
        for j in range(i + 1, len(list)):
            if list[i] + list[j] == target:
                return [i, j]
    return None

def recursive_binary_search(list, target):
    if len(list) == 0:
        return False
    else:
        midpoint = len(list) // 2
        if list[midpoint] == target:
            return True 
        else:
            if list[midpoint] < target:
                return recursive_binary_search(list[midpoint + 1:], target)
            else:
                return recursive_binary_search(list[:midpoint], target)







print(linear_search([1,2,3,4,5], 5)) 

print(binary_search([1,2,3,4,5], 5))

print(hash_search([1,2,3,4,5], 5))

print(brute_force_search([1,2,3,4,5], 5))

print(recursive_binary_search([1,2,3,4,5], 5))

BFS(너비 우선 탐색) & DFS(깊이 우선 탐색)

# 정렬/탐색 알고리즘 : https://modulabs.co.kr/blog/algorithm-python/
# Search 탐색 2 : BFS(너비 우선 탐색) & DFS(깊이 우선 탐색)

from collections import deque

graph_list = { 1: set([2, 3]),
                2: set([1, 3, 4]),
                3: set([1, 5]),
                4: set([1]),
                5: set([2,6]),
                6: set([3,4])}

root_node = 1

def bfs(graph, root):
    visited = []
    queue = deque([root])
    while queue:
        node = queue.popleft()
        if node not in visited:
            visited.append(node)
            queue += graph[node] - set(visited)
    return visited

print(bfs(graph_list, root_node))

def dfs(graph, root):
    visited = []
    stack = [root]
    while stack:
        node = stack.pop()
        if node not in visited:
            visited.append(node)
            stack += graph[node] - set(visited)
    return visited

print(dfs(graph_list, root_node))
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[python] pdf to png, 해상도 높게 저장하기  (0) 2023.10.04
[python] matrix 3.0.0  (0) 2023.10.04
[python] 알고리즘 - 정렬  (0) 2023.09.27
[python] sudoku 만들기 - 랜덤 문제  (0) 2023.09.27
[python] sudoku 만들기  (0) 2023.09.27
반응형

[python] 알고리즘 - 정렬

# 정렬 알고리즘 : https://modulabs.co.kr/blog/algorithm-python/

 

파이썬 알고리즘 정의와 종류 (정렬, 탐색)

여러 가지 알고리즘 중에서 정렬 알고리즘과 탐색 알고리즘의 정의와 종류를 설명하고 파이썬 코드로 구현한 알고리즘을 보여드립니다.

modulabs.co.kr

정렬(Sorting)

정렬은 특정한 기준에 따라 데이터를 늘어놓는 알고리즘입니다.

버블 정렬(Bubble Sort)

버블 정렬은 바로 옆에 있는 것과 비교해서 정렬하는 것입니다. 구현은 쉽지만 효율성이 매우 낮다고 알려져 있습니다.

선택 정렬(Selection Sort)

데이터를 선택 정렬은 배열에서 작은 데이터를 선별하여서 데이터를 앞으로 보내는 정렬의 일종입니다. 이 정렬도 효율은 낮습니다.

삽입 정렬(Insertion Sort)

삽입 정렬은 자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여, 자신의 위치를 찾아 삽입함으로써 정렬을 완성하는 알고리즘입니다.

퀵 정렬(Quick Sort)

퀵 정렬은 찰스 앤터니 리처드 호어가 개발한 정렬 알고리즘이다. 다른 원소와의 비교만으로 정렬을 수행하는 비교 정렬에 속한다. 퀵 정렬은 n개의 데이터를 정렬할 때, 최악의 경우에는 O(n²)번의 비교를 수행하고, 평균적으로 O(n log n)번의 비교를 수행합니다.

병합 정렬(Merge Sort)

합병 정렬 또는 병합 정렬은 O(n log n) 비교 기반 정렬 알고리즘이다. 일반적인 방법으로 구현했을 때 이 정렬은 안정 정렬에 속하며, 분할 정복 알고리즘의 하나 입니다.

힙 정렬(Heap Sort)

힙 정렬이란 최대 힙 트리나 최소 힙 트리를 구성해 정렬을 하는 방법으로서, 내림차순 정렬을 위해서는 최소 힙을 구성하고 오름차순 정렬을 위해서는 최대 힙을 구성하면 됩니다.

기수 정렬(Radix Sort)

기수 정렬은 기수 별로 비교 없이 수행하는 정렬 알고리즘이다. 기수로는 정수, 낱말, 천공카드 등 다양한 자료를 사용할 수 있으나 크기가 유한하고 사전순으로 정렬할 수 있어야 한다. 버킷 정렬의 일종으로 취급되기도 합니다.

계수 정렬(Count Sort)

계수 정렬 또는 카운팅 소트는 컴퓨터 과학에서 정렬 알고리즘의 하나로서, 작은 양의 정수들인 키에 따라 객체를 수집하는 것, 즉 정수 정렬 알고리즘의 하나 입니다.

 

# 정렬 알고리즘 : https://modulabs.co.kr/blog/algorithm-python/

import random

class Sort :
    def bubble_sort(arr):
        for i in range(len(arr)):
            for j in range(len(arr) - i - 1):
                if arr[j] > arr[j+1]:
                    arr[j], arr[j+1] = arr[j+1], arr[j]
        return arr


    def selection_sort(arr):
        for i in range(len(arr)):
            min_index = i
            for j in range(i+1, len(arr)):
                if arr[min_index] > arr[j]:
                    min_index = j
            arr[i], arr[min_index] = arr[min_index], arr[i]
        return arr


    def quick_sort(arr):
        if len(arr) <= 1:
            return arr
        pivot = arr[len(arr) // 2]
        left, right, equal = [], [], []
        for i in arr:
            if i < pivot:
                left.append(i)
            elif i > pivot:
                right.append(i)
            else:
                equal.append(i)
        return Sort.quick_sort(left) + equal + Sort.quick_sort(right)


    def merge_sort(arr):
        if len(arr) < 2:
            return arr
        
        mid = len(arr) // 2
        left = Sort.merge_sort(arr[:mid])
        right = Sort.merge_sort(arr[mid:])

        merged_arr = []
        l = r = 0
        while l < len(left) and r < len(right):
            if left[l] < right[r]:
                merged_arr.append(left[l])
                l += 1
            else:
                merged_arr.append(right[r])
                r += 1

        merged_arr += left[l:]
        merged_arr += right[r:]
        return merged_arr


    def heap_sort(arr):
        def heapify(arr, n, i):
            largest = i
            l = 2 * i + 1
            r = 2 * i + 2

            if l < n and arr[i] < arr[l]:
                largest = l

            if r < n and arr[largest] < arr[r]:
                largest = r

            if largest != i:
                arr[i], arr[largest] = arr[largest], arr[i]
                heapify(arr, n, largest)

        n = len(arr)
        for i in range(n, -1, -1):
            heapify(arr, n, i)

        for i in range(n-1, 0, -1):
            arr[i], arr[0] = arr[0], arr[i]
            heapify(arr, i, 0)

        return arr



    def radix_sort(arr):
        RADIX = 10
        placement = 1

        max_digit = max(arr)

        while placement < max_digit:
            buckets = [list() for _ in range(RADIX)]

            for i in arr:
                tmp = int((i / placement) % RADIX)
                buckets[tmp].append(i)

            a = 0
            for b in range(RADIX):
                buck = buckets[b]
                for i in buck:
                    arr[a] = i
                    a += 1

            placement *= RADIX

        return arr


    def counting_sort(arr):
        max_value = max(arr)
        m = max_value + 1
        count = [0] * m

        for a in arr:
            count[a] += 1

        i = 0
        for a in range(m):
            for c in range(count[a]):
                arr[i] = a
                i += 1
        return arr


arr = [i for i in random.sample(range(10), 10)]



print("Original array: ", arr)
print("Bubble sort: ", Sort.bubble_sort(arr))
print("Selection sort: ", Sort.selection_sort(arr))
print("Quick sort: ", Sort.quick_sort(arr))
print("Merge sort: ", Sort.merge_sort(arr))
print("Heap sort: ", Sort.heap_sort(arr))
print("Radix sort: ", Sort.radix_sort(arr))
print("Counting sort: ", Sort.counting_sort(arr))

 

반응형

'프로그래밍 > Python' 카테고리의 다른 글

[python] matrix 3.0.0  (0) 2023.10.04
[python] 알고리즘 - 탐색  (0) 2023.09.27
[python] sudoku 만들기 - 랜덤 문제  (0) 2023.09.27
[python] sudoku 만들기  (0) 2023.09.27
[python] How to send text messages with Python for Free  (0) 2023.09.26

+ Recent posts