Python 从文本文件读取点数据并返回字典

Python 从文本文件读取点数据并返回字典,python,Python,我需要读取一个文本文件并返回一个字典,其中键是城市名称,坐标是列表 以下是文件的外观: Seattle 3 26 Las_Vegas 11 10 Los_Angeles 4 8 San_Diego 7 5 cities = "cities.txt" def readPoints(infile): cityDictionary = {} with open(cities) as fh: for line in fh: command, de

我需要读取一个文本文件并返回一个字典,其中键是城市名称,坐标是列表

以下是文件的外观:

Seattle 3 26
Las_Vegas 11 10
Los_Angeles 4 8
San_Diego 7 5
cities = "cities.txt"
def readPoints(infile):
    cityDictionary = {}
    with open(cities) as fh:
        for line in fh:
            command, description = line.strip().split(' ', 1)
            cityDictionary[command] = description.strip()
    print(cityDictionary)

readPoints(cities)
以下是我迄今为止尝试过的代码:

Seattle 3 26
Las_Vegas 11 10
Los_Angeles 4 8
San_Diego 7 5
cities = "cities.txt"
def readPoints(infile):
    cityDictionary = {}
    with open(cities) as fh:
        for line in fh:
            command, description = line.strip().split(' ', 1)
            cityDictionary[command] = description.strip()
    print(cityDictionary)

readPoints(cities)
具有此选项的输出如下所示:

{'Los_Angeles': '4 8', 'Seattle': '3 26', 'San_Diego': '7 5', 'Las_Vegas': '11 10'}
我希望它看起来像这样:

{'Los_Angeles': [4.0, 8.0], 'Seattle': [3.0, 26.0], 'San_Diego': [7.0, 5.0], 'Las_Vegas': [11.0, 10.0]}

我还尝试将
command,description=line.strip().split(“”,1)
更改为
command,description=line.strip().split(“”)
,得到错误消息:
ValueError:要解压的值太多了
,您可以一开始就将它们全部解压。对于python 3:

cities = "cities.txt"
def readPoints(infile):
    cityDictionary = {}
    with open(cities) as fh:
        for line in fh:
            command, *coords = line.strip().split()
            cityDictionary[command] = [float(coord) for coord in coords]
    print(cityDictionary)

readPoints(cities)
对于python 2:

cities = "cities.txt"
def readPoints(infile):
    cityDictionary = {}
    with open(cities) as fh:
        for line in fh:
            data = line.strip().split()
            cityDictionary[data[0]] = [float(coord) for coord in data[1:]] 
    print(cityDictionary)

readPoints(cities)
*coords
将所有剩余参数放入名为
coords


注意:如果您有任意数量的坐标,也可以这样做。

您可以逐行读取,或者使用
line.split()
将拆分字符串指定给变量,如下所示。我选择使用正则表达式。如果解析一行时出错(例如,如果是空行),循环将继续到下一行输入文本。注意:我只是为了演示而使用
StringIO
——请参阅第一个示例下面的代码,了解更真实的实现

>>> indata = """
... Seattle 3 26
... Las_Vegas 11 10
... Los_Angeles 4 8
... San_Diego 7 5
... """
>>>
>>> data_dict = {}
>>>
>>> for line in StringIO(indata):
...     try:
...         loc, long, lat  = re.findall(r"\s*(\w+)\s+(\d+)\s+(\d+)", line)[0]
...         print(f"Location: {loc}\nLongitude: {long}\nLatitude: {lat}\n")
...         data_dict[loc] = (long, lat)
...     except (ValueError, IndexError):
...         pass
...         
Location: Seattle
Longitude: 3
Latitude: 26

Location: Las_Vegas
Longitude: 11
Latitude: 10

Location: Los_Angeles
Longitude: 4
Latitude: 8

Location: San_Diego
Longitude: 7
Latitude: 5

>>> data_dict
{'Seattle': ('3', '26'), 'Las_Vegas': ('11', '10'), 'Los_Angeles': ('4', '8'), 
'San_Diego': ('7', '5')}
代码在文件中读取时的外观:

>>> with open('cities.txt', 'r') as f:
...     for line in f:
...         try:
...             loc, long, lat  = re.findall(r"\s*(\w+)\s+(\d+)\s+(\d+)", line)[0]
...             print(f"Location: {loc}\nLongitude: {long}\nLatitude: {lat}\n")
...             data_dict[loc] = (long, lat)
...         except (ValueError, IndexError):
...             pass
您可以在发生异常时打印消息,或者选择将其写入调试日志

开发者Soapbox

顺便说一句,我觉得逐行读取输入文本数据并一次处理一个数据是一种很好的做法。如今,许多程序员默认采用简单的方式编写代码,读取整个文件,然后在处理前生成大量内存中的解析数据列表

他们这样做是因为期望当前系统拥有足够的资源和处理能力,并且他们的代码不会被用于处理更大的数据集。这种假设可能会持续几年,直到低效模块的积累开始导致承载此类模块的软件陷入系统瘫痪。而且他们也不能总是预见到特定类型文件的大小会随着时间的推移而增长

例如,处理源文件文本的IDE插件(除其他外)使用效率低下的算法处理数据,导致IDE消耗了很大一部分RAM,最终导致IDE运行缓慢,影响其他开放应用程序的性能

读取大数据集并非总是可以避免的,但在可以避免的地方,就应该避免。一个人不应该陷入专注于“早期优化”的工作中,但我觉得如果你知道如何编写高效的代码,你应该在离开项目和其他人继承你的代码之前第一次花时间把它做好,永远不要把它当作更大问题的一部分,永远不要修复它


Chrome是受内存过度消耗影响的应用程序的另一个例子。如果我打开了IDE,我甚至无法在我的虚拟机中打开它,否则我的虚拟机将几乎停止运行。

我只是对python非常陌生,并且基于另一个论坛问题的代码,所以我没有完全理解所有内容的含义。谢谢您的帮助,但是当我尝试使用这些建议的更改运行代码时,我得到了错误消息:
命令,coords=line.strip().split()值错误:值太多,无法解包
应该是
命令,*coords=line.strip().split()
当我放入*,不要忘记
coords
前面的*,它说的是无效的语法。我使用的是Python2.7,如果这有所不同的话。好吧,我为Python2添加了一个。为什么在
split
中将
maxslit
设置为
1