【问题标题】:Creating dicts from file in python在python中从文件创建字典
【发布时间】:2016-08-22 08:14:01
【问题描述】:

例如,我有像这样的多行文件

<<something>>   1, 5, 8
<<somethingelse>> hello
<<somethingelseelse>> 1,5,6

我需要用键创建字典

dict = { "something":[1,5,8], "somethingelse": "hello" ...}

我需要以某种方式读取 > 里面的内容并将其作为键,并且我还需要检查是否有很多元素或只有 1 个。如果只有一个,那么我将它作为字符串。如果不止一个,那么我需要将其作为元素列表。 任何想法如何帮助我? 也许是正则表达式,但我不太喜欢它们。

我很容易创建 def 正在读取文件行,但不知道如何分隔这些值:

f = open('something.txt', 'r')
lines = f.readlines()
f.close()

def finding_path():
    for line in lines:
        print line

finding_path()
f.close()

有什么想法吗?谢谢:)

【问题讨论】:

  • 那么根据什么规则有多个值?如果有逗号?那么您是否总是有 整数(您的预期输出已将数字转换为 int 值)。
  • 没有规则,但我可以检查是否有“,”标志,所以我确定会有超过 1 个值。如果没有 "," 它只是一个字符串,并且它们并不总是整数,它们可以是可能的字符串,但我们需要将它们放在一个列表中而不是单个字符串中
  • 您不需要关闭文件两次。为什么不将文件名传递给函数而不是使用全局变量?

标签: python python-2.7 file input


【解决方案1】:

假设您的键始终是单个单词,您可以使用split(char, maxSplits)。类似下面的东西

import sys

def finding_path(file_name):
    f = open(file_name, 'r')
    my_dict = {}
    for line in f:
        # split on first occurance of space
        key_val_pair = line.split(' ', 1)
        # if we do have a key seprated by a space
        if len(key_val_pair) > 1:
            key = key_val_pair[0]
            # proceed only if the key is enclosed within '<<' and '>>'
            if key.startswith('<<') and key.endswith('>>'):
                key = key[2:-2]
                # put more than one value in list, otherwise directly a string literal
                val = key_val_pair[1].split(',') if ',' in key_val_pair[1] else key_val_pair[1]

                my_dict[key] = val
    print my_dict
    f.close()

if __name__ == '__main__':
    finding_path(sys.argv[1])

使用如下文件

<<one>> 1, 5, 8
<<two>> hello
// this is a comment, it will be skipped
<<three>> 1,5,6

我得到输出

{'three': ['1', '5', '6\n'], 'two': 'hello\n', 'one': ['1', ' 5', ' 8\n']}

【讨论】:

  • 要求的输出是 {'three': [1,5,6], 'two': 'hello\n', 'one': [1, 5, 8]}
  • @DineshPundkar:你的回答也没有实现。
  • 拜托了,不用打f.readlines();您可以直接遍历文件对象。使用{} 更好地创建一个空字典(更快,因为它使用操作码,而不必查找内置并调用它)。您可能希望将文件名传递给函数而不是使用全局变量。为什么打电话给f.close()两次?您可以通过 with 语句将文件对象用作上下文管理器,并自动关闭文件(即使出现异常)。
  • 还有文件应该像 > 并且你的密钥需要是一些东西
  • 我的程序有时也会出现空行或 cmets,所以我需要清除它们。我可以避免在正则表达式 cmets 中使用 if not re.match(r'^//', line):,但是如何在正则表达式中检查该行是否为空?
【解决方案2】:

请检查以下代码:

  • 使用正则表达式获取键和值

  • 如果值列表的长度为1,则将其转换为字符串。

import re
demo_dict = {}

with open("val.txt",'r') as f:
    for line in f:
          m= re.search(r"<<(.*?)>>(.*)",line)
          if m is not None:
               k = m.group(1)
               v = m.group(2).strip().split(',')
               if len(v) == 1:
                    v = v[0]
               demo_dict[k]=v
print demo_dict

输出:

C:\Users\dinesh_pundkar\Desktop>python demo.Py
{'somethingelseelse': [' 1', '5', '6'], 'somethingelse': 'hello', 'something': [
'   1', ' 5', ' 8']}

【讨论】:

  • AttributeError: 'NoneType' 对象没有属性 'group'
  • @degath:您有与正则表达式不匹配的行;例如,该行可能为空。跳过m is None 为真的行。
  • 对,现在唯一剩下的就是跳过正则表达式不匹配的行。
  • 为什么不在之前的版本中使用if m is None:?现在你做了两个正则表达式,只需要一个。
【解决方案3】:

我的回答与 Dinesh 的类似。如果可能的话,我添加了一个函数来将列表中的值转换为数字,并添加了一些错误处理,以便如果行不匹配,则会给出有用的警告。

import re
import warnings

regexp =re.compile(r'<<(\w+)>>\s+(.*)')

lines = ["<<something>>   1, 5, 8\n",
         "<<somethingelse>> hello\n",
         "<<somethingelseelse>> 1,5,6\n"]

#In real use use a file descriptor instead of the list
#lines = open('something.txt','r')

def get_value(obj):
    """Converts an object to a number if possible, 
    or a string if not possible"""
    try:
        return int(obj)
    except ValueError:
        pass
    try:
        return float(obj)
    except ValueError:
        return str(obj)

dictionary = {}

for line in lines:    
    line = line.strip()
    m = re.search(regexp, line)
    if m is None:
        warnings.warn("Match failed on \n   {}".format(line))
        continue
    key = m.group(1)
    value = [get_value(x) for x in m.group(2).split(',')]
    if len(value) == 1: 
        value = value[0]
    dictionary[key] = value

print(dictionary)

输出

{'something': [1, 5, 8], 'somethingelse': 'hello', 'somethingelseelse': [1, 5, 6]}

【讨论】:

    猜你喜欢
    • 2018-03-29
    • 2021-05-10
    • 2021-05-15
    • 2013-11-18
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 2012-03-08
    相关资源
    最近更新 更多