You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用函数式方法在Python中实现字典列表转列表字典与文件分组

我太懂这种从Scala切换到Python后,想念函数式数据处理丝滑感的心情了!尤其是group by这类操作在Scala里简直顺手到不行,刚转Python时确实会有点摸不着头脑——不过放心,不用pandas也完全能搞定,而且用函数式风格实现的话,体验能无限接近你熟悉的Scala感觉。

一、用函数式方法分组Path列表(训练/验证集划分)

假设你已经有了which_set函数,能接收pathlib.Path对象并返回"train"或"val"这类集合名称,这里有两种纯函数式的实现方式:

方法1:字典推导式(直观简洁)

这种方式最接近Scala中groupBy的语义,直接遍历所有Path对象,按分组键筛选:

from pathlib import Path

# 示例which_set函数,你可以替换成自己的逻辑
def which_set(file_path: Path) -> str:
    return "train" if "train" in file_path.parent.name else "val"

# 你的Path列表
all_paths = [
    Path("data/train/img1.jpg"),
    Path("data/val/img2.jpg"),
    Path("data/train/img3.jpg"),
    Path("data/val/img4.jpg")
]

# 分组操作
grouped_sets = {
    set_name: [path for path in all_paths if which_set(path) == set_name]
    for set_name in {"train", "val"}
}

# 结果:{"train": [Path(...), Path(...)], "val": [Path(...), Path(...)]}

这个方法的优势是清晰直观,完全不需要额外依赖,而且直接操作Path对象,不用转成字符串。

方法2:用functools.reduce(更灵活的聚合)

如果你的分组键是动态生成的(比如不止train/val两种),用reduce来逐步聚合会更灵活:

from functools import reduce
from pathlib import Path

def which_set(file_path: Path) -> str:
    return "train" if "train" in file_path.parent.name else "val"

all_paths = [Path("data/train/img1.jpg"), Path("data/val/img2.jpg"), ...]

# 用reduce逐个将Path添加到对应分组
grouped_sets = reduce(
    lambda acc, path: acc[which_set(path)].append(path) or acc,
    all_paths,
    # 初始化空字典,如果分组键动态,也可以改成{},然后用setdefault
    {"train": [], "val": []}
)

这里利用了append返回None的特性,用or acc确保每次迭代都返回更新后的字典,和Scala中折叠(fold)操作的逻辑一致。

二、从字典列表创建列表字典的函数式实现

比如把[{"a":1, "b":2}, {"a":3, "b":4}]转换成{"a":[1,3], "b":[2,4]},同样有两种函数式思路:

方法1:字典推导式(适用于键统一的场景)

如果所有字典的键都相同,直接推导式就能搞定:

dict_list = [{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}]

list_dict = {
    key: [d[key] for d in dict_list]
    for key in dict_list[0].keys()
}

方法2:用functools.reduce(处理键不统一的情况)

如果字典列表里的键可能不一致,reduce能动态收集所有存在的键:

from functools import reduce

dict_list = [{"a":1, "b":2}, {"a":3}, {"b":4, "c":5}]

def merge_to_list_dict(acc, current_dict):
    for key, value in current_dict.items():
        # 键不存在就初始化空列表,再追加值
        acc.setdefault(key, []).append(value)
    return acc

list_dict = reduce(merge_to_list_dict, dict_list, {})
# 结果:{"a": [1,3], "b": [2,4], "c": [5]}

这个方法的灵活性更高,不管输入的字典有没有相同的键,都能正确聚合。


内容的提问来源于stack exchange,提问作者Piotr Czapla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:31:59