needmoreeasy EN 한국어
배우기

47 — 검색 — JSON에서 찾기

★★★★★ (5/5)자료 다루기
선수 지식
41 — 기록, 39 — JSON
결과물
로컬 서버나 파일에서 JSON 목록을 불러와 대소문자 구분 없이 검색하기

목록은 기록들의 모음입니다 — name과 tags가 든 딕셔너리. 검색 반복은 키워드를 물어보고 목록을 훑으며 이름이 맞는 기록을 골라냅니다. 이 가이드는 로컬 파일이나 HTTP 서버에서 목록을 불러오고 .lower()로 대소문자 구분 없이 글을 맞춥니다.

단계

  1. 기록 하나는 name과 tags 목록을 담습니다. 목록 전체는 그런 딕셔너리들의 모음이고 catalog.json으로 저장됩니다:

    [
      {"name": "Red Apple", "tags": ["fruit", "sweet"]},
      {"name": "Red Rose", "tags": ["flower", "garden"]},
      {"name": "Green Tea", "tags": ["drink", "warm"]},
      {"name": "Blueberry", "tags": ["fruit", "blue"]}
    ]
    
    실행해 보기 →
  2. 프로그램 옆 파일에서 목록을 불러오거나, 파일이 없으면 로컬 서버에서 불러옵니다. os.path.exists가 길을 고르고, 서버 부분은 76의 urlopen 줄입니다. json읽기와 loads 모두 같은 모양을 돌려줍니다 — 딕셔너리들의 목록:

    import os
    파일 사용 최신
    from json import loads
    from urllib.request import urlopen
    
    if os.path.exists("catalog.json"):
        상품들 = json읽기("catalog.json")
    else:
        url = "http://localhost:8000/catalog.json"
        상품들 = loads(urlopen(url).read().decode("utf-8"))
    
    실행해 보기 →
  3. "Red" in "Red Apple"은 대소문자를 구분해서 소문자 검색이 놓칩니다. .lower()이 문자열을 소문자로 복사하고, 양쪽에 붙이면 대소문자 구분 없는 매칭이 됩니다. 태그는 목록이라 word.lower() in 상품["tags"]이 태그 목록 전체를 확인합니다 — 문자열과 목록에 쓰는 같은 in 연산자. Red Apple이 두 번 출력됩니다:

    name = "Red Apple"
    word = "red"
    if word.lower() in name.lower():
        말해 name
    
    상품 = {"name": "Red Apple", "tags": ["fruit", "sweet"]}
    if "sweet" in 상품["tags"]:
        말해 상품["name"]
    
    실행해 보기 →
  4. found 카운터가 "없음"을 침묵 대신 진짜 답으로 바꿉니다:

    found = 0
    for 상품 in 상품들:
        if "red" in 상품["name"].lower():
            말해 f"{상품['name']}: {', '.join(상품['tags'])}"
            found = found + 1
    if found == 0:
        말해 "없음"
    
    실행해 보기 →
  5. 프로그램 전체입니다. catalog.json 옆에 search.ko.nme으로 저장합니다:

    # search.ko.nme — JSON 목록에서 찾기.
    # 실행: nme 실행 search.ko
    # search, list, quit 중 하나를 입력하세요.
    
    import os
    파일 사용 최신
    from json import loads
    from urllib.request import urlopen
    
    # 로컬 파일이나 로컬 서버에서 목록을 불러옵니다.
    if os.path.exists("catalog.json"):
        상품들 = json읽기("catalog.json")
    else:
        url = "http://localhost:8000/catalog.json"
        상품들 = loads(urlopen(url).read().decode("utf-8"))
    
    말해 f"목록: {len(상품들)}개"
    while True:
        말해 "명령: search, list, quit"
        물어봐 명령, "? "
        if 명령 == "search":
            물어봐 단어, "검색어? "
            found = 0
            for 상품 in 상품들:
                # 양쪽을 소문자로 바꾸면 Red가 red를 찾습니다.
                name = 상품["name"].lower()
                if 단어.lower() in name or 단어.lower() in 상품["tags"]:
                    말해 f"{상품['name']}: {', '.join(상품['tags'])}"
                    found = found + 1
            if found == 0:
                말해 "없음"
        elif 명령 == "list":
            for 상품 in 상품들:
                말해 상품["name"]
        elif 명령 == "quit":
            말해 "안녕!"
            break
        else:
            말해 "알 수 없는 명령"
    
    실행해 보기 →

    검색은 이름과 태그를 모두 확인하므로 red는 이름으로 Red Apple과 Red Rose를 찾고, blue는 태그를 통해 Blueberry를 찾습니다.

  6. 파이프로 명령을 넣어 실행합니다. search가 red를 찾고, list가 모든 이름을 출력하며, quit이 반복을 끝냅니다:

    printf 'search\nred\nlist\nquit\n' | nme 실행 search.ko
    
    목록: 4개
    명령: search, list, quit
    ? 검색어? Red Apple: fruit, sweet
    Red Rose: flower, garden
    명령: search, list, quit
    ? Red Apple
    Red Rose
    Green Tea
    Blueberry
    명령: search, list, quit
    ? 안녕!
    

    맞는 게 없는 키워드는 없음을 출력합니다. 서버 경로를 쓰려면 폴더에서 python3 -m http.server 8000을 시작하고 catalog.json 이름을 바꾼 뒤 실행하세요 — 같은 프로그램이 HTTP로 똑같은 목록을 가져옵니다.

직접 해보기

이름 검사를 빼고 단어.lower()를 각 상품의 태그 목록에만 맞춰 보세요. 또는 반복 뒤에 f"{found}개 찾음"을 출력해 보세요.

배운 것

  • 목록은 name과 tags가 든 딕셔너리들의 모음입니다.
  • os.path.exists가 json읽기와 loads(urlopen(...)) 사이를 고릅니다.
  • 양쪽 .lower()이 in 매칭을 대소문자 구분 없이 만듭니다.
  • in은 문자열(name)과 목록(tags) 모두에 쓸 수 있습니다.
  • found 카운터가 빈 반복과 "없음"을 구분하게 해 줍니다.

GitHub에서 이 문서 보기