Как мне вывести все элементы, содержащие одну и ту же строку букв?

#python

#python

Вопрос:

У меня есть программа, в которой есть опция поиска, которая, если курица или цыпленок есть в инвентаре, она вытащит элемент, просто набрав chi (не чувствительный к регистру). Проблема в том, как мне заставить функцию возвращать все элементы, содержащие chi?

Например, если у меня есть цыплята, цыплята, цыплята и цыплята в инвентаре, я должен иметь возможность ввести chi, и он должен распечатать всю информацию о каждом элементе.

Затронутый код (не полная программа):

 def search(self, query):
    #SEARCHING DATA BASED ON CLOSEST CHARACTER MATCH - NOT CASE SENSITIVE
    for id in self.items:
        if str(query) == id or self.items[id]['name'].lower().startswith(str(query).lower()):
            return id, self.items[id]['name'], self.items[id]['qty']
    return None
  

Полный код для целей тестирования:

 import os
import json

class Inventory:
    def __init__(self):
        #AT LAUNCH GROUPS AND LOADING FUNCTION
        self.items = {}
        self.load()

    def remove(self, ID):
        #REMOVING ITEMS FOR LISTS AND OUTPUT DOCUMENT
        del self.items[str(ID)]
        self.save()

    def add(self, ID, name, qty):
        #ADDING ITEMS FOR LISTS AND OUTPUT DOCUMENT
        self.items[str(ID)] = {"name": name, "qty": qty}
        self.save()

    def update(self, ID, update):
        #UPDATING ITEMS FOR LISTS AND OUTPUT DOCUMENT
        self.items[str(ID)]["qty"]  = update
        self.save()

    def search(self, query):
    #SEARCHING DATA BASED ON CLOSEST CHARACTER MATCH - NOT CASE SENSITIVE
        found = []
        for id in self.items:
            if str(query) == id or self.items[id]['name'].lower().startswith(str(query).lower()):
                found.append(
                    (id, self.items[id]['name'], self.items[id]['qty'])
                )
        return found

    def __str__(self):
        #FORMATTING
        out = ""
        for id, d in self.items.items():
            out  = f"ID Number : {id} nItem Name : {d['name']}nQuantity : {d['qty']}n"
            out  = "----------n"
        return out
    
    def save(self):
        #WHERE TO SAVE TO
        with open('data.txt','w') as outfile:
           json.dump(self.items, outfile)

    def load(self):
        #WHERE TO PUT DATA FROM WHEN RELAUNCHING PROGRAM
        try:
            with open('data.txt','r') as json_file:
               self.items = json.load(json_file)
        except:
            print("Can't load old inventory, starting fresh")
            self.items = {}


def menuDisplay():
    #MENU FOR PROGRAM 
    """Display the menu"""
    print('=============================')
    print('= Inventory Management Menu =')
    print('=============================')
    print('(1) Add New Item to Inventory')
    print('(2) Remove Item from Inventory')
    print('(3) Update Inventory')
    print('(4) Search Item in Inventory')
    print('(5) Print Inventory Report')
    print('(99) Quit')


def add_one_item(inventory):
    #ADDING PROMPT AND ERROR CHECKING
    print('Adding Inventory')
    print('================')
    while True:
        try:
            new_ID = int(input("Enter an ID number for the item: "))
            if inventory.search(new_ID):
                print("ID number is taken, please enter a different ID number")
                continue
            new_name = input('Enter the name of the item: ')
            new_qty = int(input("Enter the quantity of the item: "))
            inventory.add(new_ID, new_name, new_qty)
            break
        except Exception as e:
            print("Invalid choice! try again! "   str(e))
            print()


def remove_one_item(inventory):
    #REMOVING PROMPT AND ERROR CHECKING
    print('Removing Inventory')
    print('==================')
    while True:
        try:
            removing = int(input("Enter the item's ID number to remove from inventory: "))
            if inventory.search(removing):
                inventory.remove(removing)
            else:
                print("Item not in inventory")
                continue
            break
        except Exception as e:
            print("Invalid choice! try again! "   str(e))
            print()


def ask_exit_or_continue():
    #OPTION TO CONTINUE OR QUITE PROGRAM
    return int(input('Enter 98 to continue or 99 to exit: '))


def update_inventory(inventory):
    #UPDATING PROMPT AND ERROR CHECKING
    print('Updating Inventory')
    print('==================')
    while True:
        try:
            ID = int(input("Enter the item's ID number to update: "))
            if inventory.search(ID):
                update = int(input("Enter the updated quantity. Enter 5 for additional or -5 for less: "))
                inventory.update(ID, update)
            else:
                print("ID number is not in the system, please enter a different ID number")
                continue
            break
        except Exception as e:
            print("Invalid choice! try again! "   str(e))
            print()

def search_inventory(inventory):
    #SEARCHING PROMPT AND ERROR CHECKING
    print('Searching Inventory')
    print('===================')
    while True:
        try:
            search = input("Enter the name of the item: ")
            result = inventory.search(search)
            if result is None:
                print("Item not in inventory")
                continue
            else:
                ID, name, qty = result
                print('ID Number: ', ID)
                print('Item:     ', name)
                print('Quantity: ', qty)
                print('----------')
            break
        except Exception as e:
            print("Invalid choice! try again! "   str(e))
            print()


def print_inventory(inventory):
    #PRINT CURRENT LIST OF ITEMS IN INVENTORY
    print('Current Inventory')
    print('=================')
    print(inventory)


def main():
    #PROGRAM RUNNING COMMAND AND ERROR CHECKING
    inventory = Inventory()
    while True:
        try:
            menuDisplay()
            CHOICE = int(input("Enter choice: "))
            if CHOICE in [1, 2, 3, 4, 5]:
                if CHOICE == 1:
                    add_one_item(inventory)
                elif CHOICE == 2:
                    remove_one_item(inventory)
                elif CHOICE == 3:
                    update_inventory(inventory)
                elif CHOICE == 4:
                    search_inventory(inventory)
                elif CHOICE == 5:
                    print_inventory(inventory)
                exit_choice = ask_exit_or_continue()
                if exit_choice == 99:
                    exit()
            elif CHOICE == 99:
                exit()
        except Exception as e:
            print("Invalid choice! try again!" str(e))
            print()

        # If the user pick an invalid choice,
        # the program will come to here and
        # then loop back.


main()
  

Ответ №1:

Для более общего ответа, если вы просто хотите найти подмножество элементов, содержащих подстроку, это хорошее решение:

 def subset_contains(input_word, valid_words):
    match_list = [word for word in valid_words if input_word in word]
    return match_list
  

запуск этого кода:

 valid_words = ['chicken', 'cheese', 'chess', 'dog', 'coach']
print(subset_contains('ch', valid_words))
  

результат в этом выводе:

 ['chicken', 'cheese', 'chess', 'coach']
  

Вот еще несколько подробных кодов, которые могут быть больше похожи на то, что вы ищете

 #defining object, which has a name and description
class object:
    def __init__(self, name, info):
        self.name = name
        self.info = info

#returns a subset of a list where the name contains a string
def return_contains(match_name, objects):
    match_list = [obj for obj in objects if match_name in obj.name]
    return match_list

#defining objects
objects = [object('chicken', 'chicken 1'),
            object('chicken', 'chicken 2'),
            object('chicken', 'chicken 3'),
            object('coach', 'teaches chickens'),
            object('boat', 'im boat')]

#doing the filtering
result = return_contains('ch', objects)

#printing out the results
for r in result:
    print('name: {}, description: {}'.format(r.name, r.info))
  

вывод:

 name: chicken, description: chicken 1
name: chicken, description: chicken 2
name: chicken, description: chicken 3
name: coach, description: teaches chickens
  

Комментарии:

1. Возможно, @GeorgeDavidson… Как правило, идея состоит в том, чтобы предоставить как можно меньше кода, сколько необходимо, при этом предоставляя все, что необходимо. Так что, если вы хотите добавить немного больше кода, это может быть полезно

2. @GeorgeDavidson круто. пока вы это делали, я изменил свой ответ на что-то, включая фильтрацию объектов. Взгляните на это. Если моего ответа недостаточно или у вас есть какие-либо вопросы, lmk

3. кроме того, @GeorgeDavidson, несколько полезно публиковать весь ваш код, часто лучшим решением является создание нового кода, который содержит только то, что необходимо. Это называется минимально воспроизводимым кодом, и это помогает сделать stack overflow высококачественной средой, в которой каждый может учиться

4. возможно ли, чтобы вы посмотрели на другой ответ Green Cloak Guy и исправили его проблему?

Ответ №2:

Прямо сейчас вы просто возвращаете первый найденный. Вместо этого вам нужно составить список всех найденных и вернуть это:

 def search(self, query):
    #SEARCHING DATA BASED ON CLOSEST CHARACTER MATCH - NOT CASE SENSITIVE
    found = []
    for id in self.items:
        if str(query) == id or self.items[id]['name'].lower().startswith(str(query).lower()):
            found.append(
                (id, self.items[id]['name'], self.items[id]['qty'])
            )
    return found
  

Комментарии:

1. Теперь я получаю эту ошибку с вашим кодом: неверный выбор! попробуйте еще раз! недостаточно значений для распаковки (ожидалось 3, получено 2)

2. Не могли бы вы уточнить? Где возникает эта ошибка? Обратите внимание, что с помощью этого решения вам нужно будет изменить код, вызывающий функцию, для обработки списка кортежей, а не одного отдельного кортежа.

3. как только я нажму enter после ввода символов, которые я ищу. Вам нужен полный программный код?