values/test/10/blueprint-0.png,2089.0,545.0,2100.0,546.0
values/test/10/blueprint-0.png,2112.0,545.0,2136.0,554.0
我想做的是读取一个包含数百个值的 .txt
文件,如上面共享的值,以创建一个字典,其键是其中前 2 个数字的值;我的预期输出:
mydict = {
'10-0': [[2089,545,2100,545,2100,546,2089,546],
[2112,545,2136,545,2136,554,2112,554]],
}
为了解释我们如何从 4 个数字变成 8 个数字,让我们将它们视为 x1
、y1
、x2
、y2
首先,在输出中它们组合为 x1
、y1
、x2
、y1
, x2
, y2
, x1
, y2
在实际数据中,我有数百个值,因此如果开始的 2 个元素不同,我将有不同的键。假设 .txt 文件中的行以 values/test/10/blueprint-1.png
开头,则键为 '10-1'
。
我尝试过的:
import re
import itertools
file_data = [re.findall('\d+', i.strip('\n')) for i in open('ground_truth')]
print(file_data)
final_data = [['{}-{}'.format(a, b), list(map(float, c))] for a, b, *c in file_data]
new_data = {a: list(map(lambda x: x[-1], b)) for a, b in
itertools.groupby(sorted(final_data, key=lambda x: x[0]), key=lambda x: x[0])}
但是我得到了
ValueError: not enough values to unpack (expected at least 2, got 1)
而且我似乎无法将我的问题从一个包含这两行的简单文件解决到 mydict
中预期的答案。
请注意,以这一行为例 values/test/10/blueprint-0.png,2089.0,545.0,2100.0,546.0
我们将找到这些数字 [10, 0, 2089 , 0, 545, 0, 2100, 0, 546, 0]
和元素 3、5、7 和 9 中的 0
是不相关的,因为这些数字在列表中。这些可以通过打印 file_data
来查看,就像我在上面的代码中所做的那样。
最佳答案
您需要使用更复杂的正则表达式来忽略小数点 .0
值(value)观:
re.findall(r'(?<!\.)\d+', i)
这使用负向后视,忽略任何以 .
开头的数字.这将忽略 .0
, 但如果有 .01
, 然后那些超出 .0
的额外数字(或 .<digit>
)仍会被拾起。对于您的输入应该足够了。
我会在这里使用常规循环来使代码更具可读性,并使代码保持 O(N) 而不是 O(NlogN)(不需要排序):
new_data = {}
with open('ground_truth') as f:
for line in f:
k1, k2, x1, y1, x2, y2 = map(int, re.findall(r'(?<!\.)\d+', line))
key = '{}-{}'.format(k1, k2)
new_data.setdefault(key, []).append([x1, y1, x2, y1, x2, y2, x1, y2])
我硬编码了你的 x, y
这里的组合,因为您似乎有一个非常具体的所需顺序。
演示:
>>> import re
>>> file_data = '''\
... values/test/10/blueprint-0.png,2089.0,545.0,2100.0,546.0
... values/test/10/blueprint-0.png,2112.0,545.0,2136.0,554.0
... '''
>>> new_data = {}
>>> for line in file_data.splitlines(True):
... k1, k2, x1, y1, x2, y2 = map(int, re.findall(r'(?<!\.)\d+', line))
... key = '{}-{}'.format(k1, k2)
... new_data.setdefault(key, []).append([x1, y1, x2, y1, x2, y2, x1, y2])
...
>>> new_data
{'10-0': [[2089, 545, 2100, 545, 2100, 546, 2089, 546], [2112, 545, 2136, 545, 2136, 554, 2112, 554]]}
一个不错的选择是将您的输入文件视为 CSV 格式!使用 csv
module 是拆分列的好方法,之后你只需要处理第一个文件名列中的数字:
import csv, re
new_data = {}
with open('ground_truth') as f:
reader = csv.reader(f)
for filename, *numbers in reader:
k1, k2 = re.findall(r'\d+', filename) # no need to even convert to int
key = '{}-{}'.format(k1, k2)
x1, y1, x2, y2 = (int(float(n)) for n in numbers)
new_data.setdefault(key, []).append([x1, y1, x2, y1, x2, y2, x1, y2])
关于python - 如何将带有数字的数据转换为包含列表列表的字典?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49423324/