You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:12:01