【问题标题】:Implement a multimap in Python在 Python 中实现多图
【发布时间】:2019-03-25 11:55:50
【问题描述】:

我正在尝试在 Python 中实现多重映射。我有每条记录的三个字段。

序列号、名称、食物

1 John Apple
2 Bill Orange
3 Josh Apple

这里,SerialNoName 不会重复,Food 除外。

我可以在我的哈希图中插入一个键、值和查询。但是,如何与三个值建立关系。作为,我想查询,

SerialNo s where Food='Apple'
Name where Food='Apple'
Food where Name='Bill'
Get the all stored data (SerialNo, Name, Food)

我只能创建一个索引,但是如何查询每个字段。

这是我插入数据的 hashmap,

class HashMap:
    def __init__(self):
        self.store = [None for _ in range(16)]
        self.size = 0

    def put(self, key, value):
        p = Node(key, value)
        key_hash = self._hash(key)
        index = self._position(key_hash)
        if not self.store[index]:
            self.store[index] = [p]
            self.size += 1
        else:
            list_at_index = self.store[index]
            if p not in list_at_index:
                list_at_index.append(p)
                self.size += 1
            else:
                for i in list_at_index:
                    if i == p:
                        i.value = value
                        break

我不能使用 dict ,我更喜欢从头开始构建函数以用于学习目的。

【问题讨论】:

    标签: python algorithm data-structures hashmap


    【解决方案1】:

    听起来您正在尝试实现一个数据库表。这最自然地实现为一组 dicts。 (但也有一些实现更高效的库,例如 sqlite 和 pandas)

    table = {
       dict(zip(('SerialNo', 'Name', 'Food'), row))
       for row in [
          (1, 'John', 'Apple'),
          (2, 'Bill', 'Orange'),
          (3, 'Josh', 'Apple'),
       ]
    }
    

    您可以将查询作为列表推导进行。

    # SerialNo s where Food='Apple'
    [row['Food'] for row in table if row['Food'] == 'Apple']
    
    # Name where Food='Apple'
    [row['Name'] for row in table if row['Food'] == 'Apple']
    
    # Food where Name='Bill'
    [row['Food'] for row in table if row['Name'] == 'Bill']
    
    # Get the all stored data (SerialNo, Name, Food)
    table
    

    可以进行更复杂的查询。对于大型表,可以通过提前创建外部索引来提高查询效率,就像数据库引擎一样。使用带有查找键的字典并将它们指向表集中的行字典。

    name_index = {row['Name']: row for row in table}
    
    name_index['John']  # {'SerialNo': 1, 'Name': 'John', 'Food': 'Apple'}
    

    您还可以尝试使用一组命名元组作为表行而不是字典,以提高效率。这也让您可以使用点符号来访问单元格。


    新要求:

    嗨,我不能使用 dict 。我更喜欢构建用于学习目的的功能。

    好的,所以实现一个普通的哈希表并使用它而不是本机 Python 字典。如果您需要多个索引,请如上所述使用多个哈希表。


    但是,我有重复的 Food 值,如何对其进行索引?

    想想使用这个索引的查询会返回什么。这是一组使用该食物而不是单行的行,对吗?这就是您在索引哈希表中查找的值。

    {food: {row for row in table if row['Food']==food}
     for food in {row['Food'] for row in table}}
    

    使用 for 循环可能会更有效地做到这一点。

    food_index = {}
    for row in table:
        food_index.setdefault(row['Food'], set()).add(row)
    

    如果唯一索引也返回一组行而不是单行,它可能会简化您的逻辑。 (在这种情况下,该集合将包含一行。)

    name_index = {row['Name']: {row} for row in table}
    

    我仍在使用 dicts 来简明地演示该方法,但是您没有理由不能自己实现所有这些功能。甚至可以使用函数调用中的生成器表达式来完成推导,例如

    {k:v for k, v in foo}
    dict((k, v) for k, v in foo)
    

    上面的两行在功能上是等效的。当然,如果foo 已经包含对(例如zip 调用的结果),它可以简化为

    dict(foo)
    

    您可以使用自己的哈希表类代替dict


    您的多映射实现可以在初始化时创建和存储这些索引,并在从表中添加或删除行时适当地更新每个索引中的行集。改变行字典可能会使索引无效,因此将每一行设为不可变类型(如命名元组等)可能更合适(如果必须,请自行实现)。那么修改表中的一行就是添加一个新行并删除旧行。

    【讨论】:

    • 嗨,我不能使用 dict 。我更喜欢构建用于学习目的的功能。
    • 但是,我有重复的食物值,如何索引它?
    猜你喜欢
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多