Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中从文件创建dicts_Python_Python 2.7_File_Input - Fatal编程技术网

在python中从文件创建dicts

在python中从文件创建dicts,python,python-2.7,file,input,Python,Python 2.7,File,Input,例如,我有一个包含多行的文件,比如 <<something>> 1, 5, 8 <<somethingelse>> hello <<somethingelseelse>> 1,5,6 我需要以某种方式读取>中的内容并将其作为一个键,还需要检查是否有很多元素或只有1个元素。如果只有一个,那么我把它作为字符串。如果不止一个,那么我需要把它作为一个元素列表。 有什么办法帮我吗? 也许是regEx,但我不太喜欢 我很容易创建了

例如,我有一个包含多行的文件,比如

<<something>>   1, 5, 8
<<somethingelse>> hello
<<somethingelseelse>> 1,5,6
我需要以某种方式读取>中的内容并将其作为一个键,还需要检查是否有很多元素或只有1个元素。如果只有一个,那么我把它作为字符串。如果不止一个,那么我需要把它作为一个元素列表。 有什么办法帮我吗? 也许是regEx,但我不太喜欢

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

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

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

finding_path()
f.close()

有什么想法吗?谢谢:)

假设你的按键总是单个单词,你可以玩。像下面这样

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

假设你的钥匙总是一个单词,你可以玩。像下面这样

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

请检查以下代码:

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

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


请检查以下代码:

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

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


我的答案和迪内什的相似。我添加了一个函数,如果可能的话,可以将列表中的值转换为数字,并添加了一些错误处理,以便在一行不匹配时,给出有用的警告

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)

我的答案和迪内什的相似。我添加了一个函数,如果可能的话,可以将列表中的值转换为数字,并添加了一些错误处理,以便在一行不匹配时,给出有用的警告

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)


那么,根据什么规则,存在不止一个值呢?如果有逗号?你总是有整数吗(你期望的输出已经将数字转换成
int
值)。没有规则,但我可以检查是否有“,”符号,所以我确定会有超过1的值。如果没有“,”,它将只是一个字符串,它们不是所有的int,它们可以是可能的字符串,但我们需要将它们放在一个列表中,而不是一个字符串。您不需要关闭文件两次。为什么不将文件名传递到函数中,而不是使用全局变量呢?那么根据什么规则存在多个值呢?如果有逗号?你总是有整数吗(你期望的输出已经将数字转换成
int
值)。没有规则,但我可以检查是否有“,”符号,所以我确定会有超过1的值。如果没有“,”,它将只是一个字符串,它们不是所有的int,它们可以是可能的字符串,但我们需要将它们放在一个列表中,而不是一个字符串。您不需要关闭文件两次。为什么不将文件名传递到函数中而不是使用全局变量呢?所需的输出是{'three':[1,5,6],'two':'hello\n','one':[1,5,8]}@dinespundkar:您的答案也无法实现。请不要调用
f.readlines()
;您可以直接迭代文件对象。创建空字典最好使用
{}
(更快,因为它使用操作码,而不必查找内置的并调用它)。您可能希望将文件名传递到函数中,而不是使用globals。为什么要调用
f.close()
两次呢?您可以使用file对象作为上下文管理器,使用
with
语句,并自动关闭文件(即使出现异常)。此外,文件应该是这样的,并且您的密钥必须是某个内容。因此,我的程序有时会出现空行或注释,因此我需要清除它们。我可以避免在正则表达式中使用if not re.match(r'^/',line:),但如何检查正则表达式中的行是空的?必需的输出是{'three':[1,5,6],'two':'hello\n','one':[1,5,8]}@dinespundkar:您的答案也没有实现。请不要调用
f.readlines()
;您可以直接迭代文件对象。创建空字典最好使用
{}
(更快,因为它使用操作码,而不必查找内置的并调用它)。您可能希望将文件名传递到函数中,而不是使用globals。为什么要调用
f.close()
两次呢?您可以使用file对象作为上下文管理器,使用
with
语句,并自动关闭文件(即使出现异常)。此外,文件应该是这样的,并且您的密钥必须是某个内容。因此,我的程序有时会出现空行或注释,因此我需要清除它们。我可以使用if not re.match(r'^/',line:)避免在正则表达式中出现注释,但如何在正则表达式中检查该行是否为空?AttributeError:'NoneType'对象没有属性'group'@degath:您有与正则表达式不匹配的行;例如,该行可能是空的。跳过
m为None的行
是真的。现在唯一剩下的是跳过正则表达式不匹配的行。如果m为None:,为什么不在以前的版本中使用
?现在,您需要执行两个正则表达式,其中只需要一个。AttributeError:“NoneType”对象没有属性“group”@degath:您的行与正则表达式不匹配;例如,该行可能是空的。跳过
m为None的行
是真的。现在唯一剩下的是跳过正则表达式不匹配的行。如果m为None:
,为什么不在以前的版本中使用
?现在您需要两个正则表达式,其中只需要一个正则表达式。
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]}