为文件夹中的文件生成dictonary元素列表

时间:2017-03-23 13:18:34

标签: python list python-3.x dictionary

我正在创建一个列出目录中现有文件的脚本,然后将它们保存到字典列表中。在目录中有两种类型的图像," foo"和" bar",在名称的末尾有一个标识符,用于知道应该查看它们的位置,例如:

foo_1.jpg
foo_2.jpg
foo_5.jpg
bar_1.jpg
bar_2.jpg
bar_3.jpg

我希望得到下一个结果:

files = [ {'position': 1, 'foo': '/img/foo_1.jpg','bar': '/img/bar_1.jpg'},
          {'position': 2, 'foo': '/img/foo_2.jpg','bar': '/img/bar_2.jpg'},
          {'position': 3, 'foo': '','bar': '/img/bar_3.jpg',
          {'position': 5, 'foo': '/img/foo_5.jpg','bar': ''} ]

我的代码是:

def files_in_folder(folder_name):
    folder_path = os.path.join(current_app.config['UPLOAD_FOLDER'],   'files', str(folder_name))
    data = []
    if not os.path.isdir(folder_path):
        return [{}, {}, {}, {}, {}, {}, {}, {}, {}]
    else:
        for filename in os.listdir(folder_path):
            position = int(re.search('[0-9]+', filename).group())
            if "foo" in filename:
                foo_register = {'position': position,
                                'foo': folder_path + '/' + filename, 
                                'bar': ''}
            else:
                bar_register = {'position': position,
                                'foo': '', 
                                'bar': folder_path + '/' + filename }
            register = {**foo_register, **bar_register}
            data.insert(position-1, register)
            print(data) 

我的结果是:

[{'foo': '', 'bar': 'uploads/campaigns/1/bar_1.png', 'position': 1},
 {'foo': '', 'bar': 'uploads/campaigns/1/bar_2.png', 'position': 2},
 {'foo': '', 'bar': 'uploads/campaigns/1/bar_3.png', 'position': 3},
 {'foo': 'uploads/campaigns/1/foo_1.png', 'bar': '', 'position': 1,
 {'foo': '', 'bar': 'uploads/campaigns/1/bar_3.png', 'position': 3}]

我的代码中缺少什么?这是最好的pythonic方式吗?

提前致谢。

3 个答案:

答案 0 :(得分:5)

显然,我的HD上没有这些文件,所以这里有一些处理文件名列表的代码,但是为了你的目的,它应该不难调整。

此代码的核心是辅助函数CREATE TABLE `temp_table` (id int NOT NULL PRIMARY_KEY, `timestamp` int NOT NULL); INSERT INTO `temp_table` (`id`, `timestamp`) SELECT a.id, MAX(b.`timestamp`) FROM `your_table` a LEFT JOIN `your_table` b ON b.`id` < a.`id` WHERE a.`timestamp` = 0 AND b.`timestamp` != 0 GROUP BY a.`id`; UPDATE `your_table` a INNER JOIN `temp_table` b ON b.`id` = a.`id` SET a.`timestamp` = b.timestamp; DROP TABLE `temp_table` ; ,它从文件名中提取位置(parse_name)和图像类型信息(pos)。

按照你想要的方式组织这些信息我把它写成了一个词典。然后,我们对外部字典的键进行排序,以创建所需的字典列表。我们使用数字排序,以便kind不会在11之前排序等等。

2

<强>输出

import os.path
from pprint import pprint

data = '''\
/img/foo_1.jpg
/img/foo_2.jpg
/img/foo_5.jpg
/img/bar_1.jpg
/img/bar_2.jpg
/img/bar_3.jpg
'''.splitlines()

def parse_name(s):
    fname = os.path.basename(s)
    fbase, _ = os.path.splitext(fname)
    kind, pos = fbase.split('_')
    return kind, int(pos)

files_dict = {} 
for s in data:
    kind, pos = parse_name(s)
    d = files_dict.setdefault(pos, {'position': pos})
    d[kind] = s

pprint(files_dict)
print()

files_list = [files_dict[k] for k in sorted(files_dict.keys(), key=int)]
pprint(files_list)

实际上,我们不需要那种排序键功能,因为{1: {'bar': '/img/bar_1.jpg', 'foo': '/img/foo_1.jpg', 'position': 1}, 2: {'bar': '/img/bar_2.jpg', 'foo': '/img/foo_2.jpg', 'position': 2}, 3: {'bar': '/img/bar_3.jpg', 'position': 3}, 5: {'foo': '/img/foo_5.jpg', 'position': 5}} [{'bar': '/img/bar_1.jpg', 'foo': '/img/foo_1.jpg', 'position': 1}, {'bar': '/img/bar_2.jpg', 'foo': '/img/foo_2.jpg', 'position': 2}, {'bar': '/img/bar_3.jpg', 'position': 3}, {'foo': '/img/foo_5.jpg', 'position': 5}] 已经转换为pos中的int。哎呀! :)所以我们可以这样做:

parse_name

files_list = [files_dict[k] for k in sorted(files_dict.keys())] 循环可以压缩到:

for

虽然这比之前的版本更加神秘。 ;)

for s in data:
    kind, pos = parse_name(s)
    files_dict.setdefault(pos, {'position': pos})[kind] = s

使用密钥files_dict.setdefault(pos, {'position': pos}) files_dict中获取子字典。如果它不存在,则使用初始键值对pos创建。

然后我们使用('position', pos)更新该子字典,其中(kind, s)是当前文件的完整文件名。

答案 1 :(得分:1)

  1. 尝试使用filename.startswith('bar')filename.startswith('foo')区分foo_1.jpgbar_1.jpg

  2. 尝试使用position=int(os.path.splitext(filename)[0].split('_')[-1])代替re

    1. 不要使用register = {**foo_register, **bar_register}
    2. e.g。

      a={'foo': '', 'bar': 'uploads/campaigns/1/bar_1.png', 'position': 1}
      b={'foo': 'uploads/campaigns/1/foo_.png', 'bar': '', 'position': 1}
      
      print({**a,**b})
      

      输出:

      {'foo': 'uploads/campaigns/1/foo_.png', 'bar': '', 'position': 1}
      

      我认为这就是你得到意想不到的结果的原因。

      你可以试试这个:

      a.update({k:v for k,v in b.items() if v})
      
      print(a)
      

      输出:

      {'foo': 'uploads/campaigns/1/foo_.png', 'bar': 'uploads/campaigns/1/bar_1.png', 'position': 1}
      

答案 2 :(得分:0)

import os, re
cwd = os.getcwd()
print cwd


def update(li, pos, path, key):
    added = False
    if len(li) == 0:
        di=dict()
        di["position"] = int(pos)
        di[key] = path
        li.append(di)
        added = True        
    else:
        for di in li:
            if di["position"]==pos:                
                di[key] = path
                added = True


if not added:
    di=dict()
    di["position"] = int(pos)
    di[key] = path
    li.append(di)    



li = []
for filename in os.listdir(cwd+r'/try'):        # folder name where my files are.
    position = int(re.search('[0-9]+', filename).group())
    print filename, position
    path = cwd + '/' + filename
    if "foo" in filename:        
        update(li, position, path, "foo")
    elif "bar" in filename:
        update(li, position, path, "bar")

print li