【问题标题】:Unit Conversion with Lists and Dictionaries使用列表和字典进行单位转换
【发布时间】:2019-12-04 19:16:14
【问题描述】:

我正在做一个项目,该项目需要我创建一个函数 unit_convertor('filename', D),它将文本文件中写入的所有长度、文件大小和时间单位转换为目标单位。 D 是一个字典,它指定要转换为哪些单位的长度、文件大小和时间。因此,如果我们想将长度转换为厘米,D 将是 {'length':'cm'}

例如,如果 test.txt 包含 '计算机有 8 GB 的 RAM,并且能够在 120 秒内完成操作。',并且 D 为 {'filesize':'KB ', 'time':'min'},输出将是'计算机有 8000 KB 的 RAM,并且能够在 2 分钟内完成操作。'

到目前为止,我已经成功地将文本转换为一个列表,每个单词都是一个字符串,每个数字都是一个浮点数。我正在努力的是如何将数字乘以所需的因子以使其与单位匹配,以及如何使用上面的字典替换单位。我已经阅读了字典的使用,但仍然对如何创建此功能感到非常迷茫。

这是我到目前为止的代码,我更专注于让代码与定义的文本文件一起工作,以确保它在创建函数之前工作:

f = open('example_text.txt')
fstring = f.read()
fstring = fstring.replace('\n',"")
lista = fstring.split()

listb = []
for i in lista:
    try:
        listb.append(float(i))
    except ValueError:
        listb.append(i)

我对 Python 很陌生,我真的很挣扎!

有人告诉我,编写 3 个函数是最简单的,一个用于转换时间,一个用于长度,一个用于文件大小,并在主函数中调用它们。如果我能弄清楚如何转换一种类型的单位,我可以很容易地找出另外两种。

【问题讨论】:

    标签: python list dictionary ipython list-comprehension


    【解决方案1】:

    对于初学者来说,这不是一件容易的事。你有几个步骤:

    1. 将文本拆分为单词
    2. 找到单位和相关值
    3. 将源单位值转换为目标单位值
    4. 替换单词中的单位值并重新组合文本。

    这是一个概念证明(为了简洁起见,我使用了很多列表推导,但您应该将它们扩展为函数)。让我们试试你的例子:

    >>> sentence = "The computer had 8 GB of RAM, and was able to complete the operation in 120 sec."
    

    将文本拆分成单词

    首先,您需要将句子解析为块。使用正则表达式。模式\W 匹配所有不是单词的东西。使用括号,您可以保留分隔符:

    >>> import re
    >>> chunks = re.split("(\W)", sentence)
    >>> chunks
    ['The', ' ', 'computer', ' ', 'had', ' ', .... , '120', ' ', 'sec', '.', '']
    

    重新组合文本很容易:

    >>> "".join(chunks)
    'The computer had 8 GB of RAM, and was able to complete the operation in 120 sec.'
    

    找到单位和相关值

    您对空间不感兴趣。使用enumerate 获取索引并删除空格(c.strip()False):

    >>> enumerated_chunks = [(i, c) for i, c in enumerate(chunks) if c.strip()]
    >>> enumerated_chunks
    [(0, 'The'), (2, 'computer'), (4, 'had'), (6, '8'), (8, 'GB'), (10, 'of'), (12, 'RAM'), (13, ','), (16, 'and'), (18, 'was'), (20, 'able'), (22, 'to'), (24, 'complete'), (26, 'the'), (28, 'operation'), (30, 'in'), (32, '120'), (34, 'sec'), (35, '.')]
    

    假设您有两个单位族:大小和时间。

    >>> source_units = ('gb', 'sec') # ordered : sizes then times
    

    如果我们 zipenumerated_chunks 列表本身,我们有几个连续的块:

    >>> list(zip(enumerated_chunks, enumerated_chunks[1:]))
    [((0, 'The'), (2, 'computer')), ((2, 'computer'), (4, 'had')), ..., ((34, 'sec'), (35, '.'))]
    

    假设你总是有单位后面的值(这是一个强假设),你将在句子中查找单位,并存储单位前面的值:

    >>> value_units = []
    >>> for (i, v), (j, u) in zip(enumerated_chunks, enumerated_chunks[1:]):
    ...     u = u.casefold() # compare lowercase strings
    ...     if u in source_units and v.isdigit(): # a unit predeeded by an integer
    ...         value_units.append(((i, float(v)), (j, u), source_units.index(u))) # store the index of the family
    >>> value_units
    [((6, 8.0), (8, 'gb'), 0), ((32, 120.0), (34, 'sec'), 1)]
    

    将源单位值转换为目标单位值

    单位之间的转换表是一个矩阵,但我们可以想象我们有一个值为 1 的参考单位,其他只是倍数:

    >>> sizes = {'gb':10**9, 'mb':10**6, 'kb':10**3, 'b':1}
    >>> times = {'hour':3600, 'min':60, 'sec':1}
    >>> families = (sizes, times) # same order as source_units
    

    让目标单位:

    >>> target_units = ('mb', 'min') # ordered as families
    

    我们得到目标单位并想找到家庭:

    >>> value_units_and_more = [((i, v), (j, u), target_units[f], families[f]) for (i, v), (j, u), f in value_units]
    >>> value_units_and_more # you should use classes instead of tuples of tuples
    [((6, 8.0), (8, 'gb'), 'mb', {'gb': 1000000000, 'mb': 1000000, 'kb': 1000, 'b': 1}), ((32, 120.0), (34, 'sec'), 'min', {'hour': 3600, 'min': 60, 'sec': 1})]
    >>> indexed_chunks = [((i, v*vals[su]/vals[tu]), (j, tu)) for (i, v), (j, su), tu, vals in value_units_and_more]
    >>> indexed_chunks
    [((6, 8000.0), (8, 'mb')), ((32, 2.0), (34, 'min'))]
    

    替换单词中的单位值并重新组合文本

    我们将元组展平并创建一个字典index -> new word

    >>> new_chunk_by_index = dict(t for ts in indexed_chunks for t in ts)
    >>> new_chunk_by_index
    {6: 8000.0, 8: 'mb', 32: 2.0, 34: 'min'}
    

    并替换单词:

    >>> "".join(str(new_chunk_by_index.get(i, chunk)) for i, chunk in enumerate(chunks))
    'The computer had 8000.0 mb of RAM, and was able to complete the operation in 2.0 min.'
    

    d.get(i, chunk) 取 dict new_chunk_by_index 中映射到 i 的值,如果没有值则离开 chunks。)

    警告:这只是概念验证。肯定有很多边缘情况:想想复数、浮点值、单位在值之前的情况......


    您还有另一个(也许更简单)的解决方案:使用re.sub 定位数字后跟一个单位,repl 是一个执行上述转换的函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-23
      • 2021-10-13
      • 1970-01-01
      相关资源
      最近更新 更多