【问题标题】:How can I transform my data with numbers to a dictionary containing lists of lists?如何将带有数字的数据转换为包含列表列表的字典?
【发布时间】:2018-03-22 07:58:07
【问题描述】:
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 文件,就像上面共享的值一样,创建一个字典,其键是其中前两个数字的值;我的预期输出:

mydict = {
    '10-0': [[2089,545,2100,545,2100,546,2089,546], 
             [2112,545,2136,545,2136,554,2112,554]],
}

为了解释我们如何从 4 个数字变为 8 个数字,让我们首先将它们视为 x1y1x2y2,然后在输出中将它们组合为 x1、@987654329 @、x2y1x2y2x1y2

在实际数据中,我有数百个值,因此如果起始 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 中的 0s 是无关紧要的,因为这些数字在列表中。这些可以通过打印file_data 来查看,就像我在上面的代码中所做的那样。

【问题讨论】:

    标签: python python-3.x list dictionary


    【解决方案1】:

    您需要使用更复杂的正则表达式来忽略小数 .0 值:

    re.findall(r'(?<!\.)\d+', i)
    

    这使用否定的后视,忽略前面有 . 的任何数字。这将忽略.0,但如果有.01,则仍会拾取.0(或.&lt;digit&gt;)之外的那些额外数字。对于您的输入应该足够了。

    我会在这里使用常规循环来使代码更具可读性,并保持代码 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 模块是拆分列的好方法,之后您只需要处理第一个文件名列中的数字:

    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])
    

    【讨论】:

      猜你喜欢
      • 2019-04-21
      • 1970-01-01
      • 2018-10-10
      • 2022-10-13
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多