如何修复HashMap相关的类型错误与属性错误?
修复基于HashMap的库存与订单管理程序错误
核心问题分析
程序触发TypeError/AttributeError的根本原因是自定义HashMap类未实现Python字典的核心操作接口(如[]访问、in判断、items()遍历),同时CSV数据读取和部分函数逻辑存在细节错误。
具体修复方案
1. 完善HashMap类的核心方法
为HashMap添加兼容字典操作的魔术方法,解决属性/类型错误:
__getitem__: 支持map[key]取值__setitem__: 支持map[key] = value赋值__contains__: 支持key in map判断items(): 支持遍历所有键值对- 为LinkedList添加
iterate()方法,配合HashMap的items()实现遍历
2. 修复CSV数据读取逻辑
处理CSV字段中的引号和多余空格,拆分复杂字段为结构化数据:
- 用
strip('" ')清理每个字段的引号和首尾空格 - 将
products拆分为物品列表,distance拆分为坐标列表并转为float类型 - 跳过CSV表头,避免无效数据导入
3. 修正函数逻辑与调用
- 为
inventory_overview补充参数,适配当前数据结构(无price字段,仅统计数量) - 为所有查询函数添加存在性检查,避免键不存在时报错
- 修正菜单选项3的拼写错误(
dislpay→display)
4. 修正CSV数据笔误
将serialised_data.csv中的"Items 4"改为"Item 4",确保数据一致性
完整修复代码
import csv from math import sin, cos, sqrt, atan2 class Node: def __init__(self, key, value): self.key = key self.value = value self.next = None class LinkedList: def __init__(self): self.head = None def search(self, key): curr = self.head while curr != None: if curr.key == key: return curr curr = curr.next return None def insert(self, key, value): node = Node(key, value) node.next = self.head self.head = node def delete(self, key): prev = None curr = self.head while curr != None: if curr.key == key: if prev == None: self.head = curr.next else: prev.next = curr.next return True prev = curr curr = curr.next return False def iterate(self): curr = self.head while curr != None: yield curr.key, curr.value curr = curr.next class HashMap: def __init__(self, capacity=16): self.capacity = capacity self.size = 0 self.table = [LinkedList() for _ in range(capacity)] def _hash(self, key): return hash(key) % self.capacity def get(self, key): index = self._hash(key) node = self.table[index].search(key) if node: return node.value return None def put(self, key, value): index = self._hash(key) node = self.table[index].search(key) if node: node.value = value else: self.table[index].insert(key, value) self.size += 1 if self.size > self.capacity * 0.75: self._resize() def delete(self, key): index = self._hash(key) if self.table[index].delete(key): self.size -= 1 def _resize(self): self.capacity *= 2 new_table = [LinkedList() for _ in range(self.capacity)] for bucket in self.table: curr = bucket.head while curr != None: index = self._hash(curr.key) new_table[index].insert(curr.key, curr.value) curr = curr.next self.table = new_table # 兼容字典操作的魔术方法 def __getitem__(self, key): return self.get(key) def __setitem__(self, key, value): self.put(key, value) def __contains__(self, key): return self.get(key) is not None def items(self): for bucket in self.table: yield from bucket.iterate() # 初始化数据容器 location_map = HashMap() item_map = HashMap() order_map = HashMap() def load_location_data(): with open('location_data.csv', 'r') as file: reader = csv.reader(file) next(reader) # 跳过表头 for row in reader: location_name = row[0].strip('" ') # 拆分并清理物品列表 products = [item.strip('" ') for item in row[1].strip('" ').split(',')] # 拆分并转换坐标为float coords = [float(coord.strip('" ')) for coord in row[2].strip('" ').split(',')] location_map[location_name] = {'products': products, 'coords': coords} def load_order_data(): with open('order_data.csv', 'r') as file: reader = csv.reader(file) next(reader) # 跳过表头 for row in reader: order_id = row[0].strip('" ') # 拆分并清理位置列表 locations = [loc.strip('" ') for loc in row[1].strip('" ').split(',')] order_map[order_id] = locations def load_serialised_data(): with open('serialised_data.csv', 'r') as file: reader = csv.reader(file) next(reader) # 跳过表头 for row in reader: location_name = row[0].strip('" ') item = row[1].strip('" ') quantity = int(row[2].strip('" ')) if location_name not in item_map: item_map[location_name] = {} item_map[location_name][item] = quantity def find_location_inventory(): location_name = input("Enter location name: ") if location_name not in location_map: print(f"Location {location_name} not found") return inventory = location_map[location_name]['products'] print(f"Location inventory for {location_name}:") for item in inventory: print(item) def find_distance(): start_location = input("Enter starting location: ") end_location = input("Enter ending location: ") if start_location not in location_map or end_location not in location_map: print("One or both locations not found") return start_coords = location_map[start_location]['coords'] end_coords = location_map[end_location]['coords'] # 哈弗辛公式计算距离 earth_radius = 6371.01 # km lat1, lon1 = start_coords lat2, lon2 = end_coords delta_lat = lat2 - lat1 delta_lon = lon2 - lon1 a = (sin(delta_lat / 2)) ** 2 + cos(lat1) * cos(lat2) * (sin(delta_lon / 2)) ** 2 c = 2 * atan2(sqrt(a), sqrt(1 - a)) distance = earth_radius * c print(f"Distance from {start_location} to {end_location}: {distance:.2f} km") def find_order_route(): order_id = input("Enter order ID: ") if order_id not in order_map: print(f"Order {order_id} not found") return locations = order_map[order_id] # 检查所有位置是否存在 for loc in locations: if loc not in location_map: print(f"Location {loc} in order {order_id} not found") return print(f"Route for order {order_id}:") total_distance = 0 for i in range(len(locations) - 1): start_location = locations[i] end_location = locations[i + 1] start_coords = location_map[start_location]['coords'] end_coords = location_map[end_location]['coords'] # 哈弗辛公式计算距离 earth_radius = 6371.01 # km lat1, lon1 = start_coords lat2, lon2 = end_coords delta_lat = lat2 - lat1 delta_lon = lon2 - lon1 a = (sin(delta_lat / 2)) ** 2 + cos(lat1) * cos(lat2) * (sin(delta_lon / 2)) ** 2 c = 2 * atan2(sqrt(a), sqrt(1 - a)) distance = earth_radius * c total_distance += distance print(f"From {start_location} to {end_location}: {distance:.2f} km") print(f"Total distance for order {order_id}: {total_distance:.2f} km") def location_overview(): print("Location overview:") for location, data in location_map.items(): print(f"{location}: {len(data['products'])} items in inventory") def inventory_overview(inventory_map): total_items = 0 print("Inventory overview:") for loc, items in inventory_map.items(): print(f"\n{loc}:") for item, quantity in items.items(): print(f"{item.capitalize()}: {quantity} units") total_items += quantity print(f"\nTotal number of items across all locations: {total_items}") def save_data(): with open('serialised_data.csv', 'w', newline='') as file: writer = csv.writer(file) writer.writerow(["Location", "Items", "Quantity"]) # 写入表头 for loc, items in item_map.items(): for item, quantity in items.items(): writer.writerow([loc, item, quantity]) print("Data saved successfully") # 菜单循环 while True: print("Welcome to the Interactive Menu:") print("1. Load data") print("2. Find and display location Inventory") print("3. Find and display distance between two locations") print("4. Find and display route for collecting order") print("5. Location Overview") print("6. Inventory Overview") print("7. Save data") print("8. Exit") choice = input("Select which option you would like to choose: ") if choice == "1": load_location_data() load_order_data() load_serialised_data() print("Data successfully loaded") elif choice == "2": find_location_inventory() elif choice == "3": find_distance() elif choice == "4": find_order_route() elif choice == "5": location_overview() elif choice == "6": inventory_overview(item_map) elif choice == "7": save_data() elif choice == "8": print("Exiting the interactive menu") break else: print("Invalid option was selected")
修正后的serialised_data.csv
"Location", "Items", "Quantity" "Location A", "Item 1", "4" "Location A", "Item 2", "5" "Location B", "Item 5", "2" "Location C", "Item 2", "7" "Location D", "Item 4", "9" "Location D", "Item 3", "10"
内容的提问来源于stack exchange,提问作者Rasal.A
相关产品推荐
相关产品推荐

