当前位置: 首页 > 面试题库 >

存储一组四个(或更多)值的最佳数据结构是什么?

白志勇
2023-03-14
问题内容

说我有以下内容variables及其对应的内容,values它们代表一个record

name = 'abc'
age = 23
weight = 60
height = 174

请注意,value可能是不同的typesstringintegerfloat,引用到任何-其他对象,等等)。

将会有很多records(至少>
100,000)。当所有这四个(实际上是)放在一起时,每个record都会。换句话说,不存在与所有4个相同的事物。unique``variables``values``record``values

我试图找到一个高效的数据结构,Python这将让我(商店)获取records基于其中任何一项variableslog(n)时间复杂度。

例如:

def retrieve(name=None,age=None,weight=None,height=None) 
    if name is not None and age is None and weight is None and height is None:
        /* get all records with the given name */
    if name is None and age is not None and weight is None and height is None:
        /* get all records with the given age */
    ....
    return records

retrieve调用方式如下:

retrieve(name='abc')

以上应该返回 [{name:'abc', age:23, wight:50, height=175}, {name:'abc', age:28, wight:55, height=170}, etc]

retrieve(age=23)

以上应该返回 [{name:'abc', age:23, wight:50, height=175}, {name:'def', age:23, wight:65, height=180}, etc]

而且,variables将来我可能需要在此记录中再添加一两个。例如,说sex = 'm'。因此,该retrieve功能必须是可伸缩的。

因此,在短期:是否有一个数据结构,Python这将使storing a recordncolumns(姓名,年龄,性别,体重,身高等),retrieving records的基于任何(一个)columnlogarithmic(或理想constant - O(1)查找时间)的复杂性?


问题答案:

Python内置了一个单一的数据结构,可以满足您的所有需求,但是要实现目标并相当有效地使用它,可以很容易地结合使用它们。

例如,假设您输入的是逗号分隔值文件中的以下数据,该文件的employees.csv名称定义如第一行所示:

name,age,weight,height
Bob Barker,25,175,6ft 2in
Ted Kingston,28,163,5ft 10in
Mary Manson,27,140,5ft 6in
Sue Sommers,27,132,5ft 8in
Alice Toklas,24,124,5ft 6in

下面的工作代码说明了如何将这些数据读取和存储到记录列表中,并自动创建单独的查找表以查找与每个记录中的字段所包含的值相关联的记录。

记录是创建类的实例,通过namedtuple它可以非常有效地利用内存,因为每个记录都缺少__dict__类实例通常包含的属性。使用它们将可以使用点语法(例如)按名称访问每个字段record.fieldname

查找表是defaultdict(list)实例,它们平均提供类似于字典的 O
(1)查找时间,并且还允许将多个值与每个值相关联。因此,查找关键字是要查找的字段值的值,并且与之相关的数据将是具有该值Personemployees列表中存储的记录的整数索引的列表,因此它们都将相对较小。

请注意,该类的代码完全是数据驱动的,因为它不包含任何硬编码的字段名,这些字段名全部在读取时从csv数据输入文件的第一行获取。当然,在使用实例时,所有retrieve()方法调用必须提供有效的字段名称。

更新资料

修改为在首次读取数据文件时不为每个字段的每个唯一值创建查找表。现在,retrieve()方法“懒惰”仅在需要时创建它们(并保存/缓存结果以备将来使用)。也已修改为可在Python
2.7+(包括3.x)中使用。

from collections import defaultdict, namedtuple
import csv

class DataBase(object):
    def __init__(self, csv_filename, recordname):
        # Read data from csv format file into a list of namedtuples.
        with open(csv_filename, 'r') as inputfile:
            csv_reader = csv.reader(inputfile, delimiter=',')
            self.fields = next(csv_reader)  # Read header row.
            self.Record = namedtuple(recordname, self.fields)
            self.records = [self.Record(*row) for row in csv_reader]
            self.valid_fieldnames = set(self.fields)

        # Create an empty table of lookup tables for each field name that maps
        # each unique field value to a list of record-list indices of the ones
        # that contain it.
        self.lookup_tables = {}

    def retrieve(self, **kwargs):
        """ Fetch a list of records with a field name with the value supplied
            as a keyword arg (or return None if there aren't any).
        """
        if len(kwargs) != 1: raise ValueError(
            'Exactly one fieldname keyword argument required for retrieve function '
            '(%s specified)' % ', '.join([repr(k) for k in kwargs.keys()]))
        field, value = kwargs.popitem()  # Keyword arg's name and value.
        if field not in self.valid_fieldnames:
            raise ValueError('keyword arg "%s" isn\'t a valid field name' % field)
        if field not in self.lookup_tables:  # Need to create a lookup table?
            lookup_table = self.lookup_tables[field] = defaultdict(list)
            for index, record in enumerate(self.records):
                field_value = getattr(record, field)
                lookup_table[field_value].append(index)
        # Return (possibly empty) sequence of matching records.
        return tuple(self.records[index]
                        for index in self.lookup_tables[field].get(value, []))

if __name__ == '__main__':
    empdb = DataBase('employees.csv', 'Person')

    print("retrieve(name='Ted Kingston'): {}".format(empdb.retrieve(name='Ted Kingston')))
    print("retrieve(age='27'): {}".format(empdb.retrieve(age='27')))
    print("retrieve(weight='150'): {}".format(empdb.retrieve(weight='150')))
    try:
        print("retrieve(hight='5ft 6in'):".format(empdb.retrieve(hight='5ft 6in')))
    except ValueError as e:
        print("ValueError('{}') raised as expected".format(e))
    else:
        raise type('NoExceptionError', (Exception,), {})(
            'No exception raised from "retrieve(hight=\'5ft\')" call.')

输出:

retrieve(name='Ted Kingston'): [Person(name='Ted Kingston', age='28', weight='163', height='5ft 10in')]
retrieve(age='27'): [Person(name='Mary Manson', age='27', weight='140', height='5ft 6in'),
                     Person(name='Sue Sommers', age='27', weight='132', height='5ft 8in')]
retrieve(weight='150'): None
retrieve(hight='5ft 6in'): ValueError('keyword arg "hight" is an invalid fieldname')
                           raised as expected


 类似资料:
  • 前面学习 数据结构的过程中,总是使用数组作为 顺序表的底层实现,给我们一种 "数据结构中,数组的作用就是实现顺序表" 的错误认识。其实,数组的作用远不止于此。 本节将从数据结构的角度讲解 数组存储结构。 本节所讲的数组,要将其视为一种存储结构,与平时使用的数组基本数据类型区分开。 一说起数组,我们的印象中数组往往是某一门编程语言中包含的具体数据类型,其实不然。 从本质上讲,数组与顺序表、 链表、

  • 问题内容: 这个问题已经在这里有了答案 : 8年前关闭。 可能重复: 多语言数据库的架构 这是一个例子: 问题: 每种新语言都需要修改表结构。 这是另一个例子: 问题是: 每种新语言都需要创建新表,并且每个表中都有“价格”字段重复。 这是另一个例子: 问题: 难吗? 问题答案: 您的第三个示例实际上是通常解决问题的方式。努力,但可行。 从翻译表中删除对产品的引用,然后将翻译的引用放在您需要的地方(

  • 问题内容: 如果我需要通过一个“动作”来更新或插入到多个表中,请调用一个保存信息的示例,其中有多个包含“信息”的表。 出于参数考虑,可以说我们有下表: 姓名地址汽车工作 每次调用保存信息时,都会将其中的每个表插入其中。 哪个更好: 获取必须写入名称表的数据。调用InsertOnSubmit并调用SubmitChanges 获取必须写入地址表的数据。调用InsertOnSubmit并调用Submit

  • 为了保存数据,我将使用一个SET操作,即: 然后,为了更新数据,我将使用两个操作(GET+SET),即: 选项2:单值多键 我对方案1的赞成/反对意见 备选方案1优点: 更好的数据库组织,因为每个用户只有一个密钥 通过一个GET操作,我将拥有所有JSON数据 要更新所有JSON字段,我将只使用两个操作(GET+SET) 数据库的文件大小将更小 null 如果希望并发修改JSON负载(非原子读取-修

  • 我有一个游戏,在MySQL数据库中存储boss在简单模式和硬模式下的杀人记录。有14个老板。我想存储一个球员杀死一个老板的次数和难度。我有几个选择,我可以看到。。 为每个boss以及每个难度在表中创建一个单独的列。例如。 创建两个存储数字序列的字段,这些数字可以稍后提取出来,以便在PHP中进行比较。其中easykills是一个由28个字符组成的字符串,每2个字符就有一个计数器,用于计算boss被杀

  • 我有一个存储库层,有许多方法组合,以匹配搜索标准…重用这个标准的最佳方法是什么?我认为像FindByNameAndidandBirthdayandAccouncAnumber这样的方法名称不是一个好主意!谢了! }