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

基于ID与父ID将CSV扁平目录转为树形层级并打印(Java/Python)

解决方案:扁平CSV目录结构转树形层级(含目录总大小计算)

我之前也处理过类似的扁平结构转树形的需求,这个问题的核心是用字典/哈希表快速映射节点ID和对应对象,这样能高效建立父子关系,再通过递归完成目录大小计算和层级打印。下面给你Python和Java两种实现方案,完全匹配你的需求:


Python 实现

思路

  1. 用类封装每个目录/文件节点,包含所有字段以及子节点列表、目录总大小属性
  2. 把所有节点存入ID映射字典,方便快速查找父节点
  3. 遍历节点建立父子关联,根节点(parentId为空的节点)单独收集
  4. 递归计算目录总大小:目录大小 = 所有子文件大小 + 所有子目录的总大小
  5. 递归打印树形结构,按层级缩进

完整代码

class Node:
    def __init__(self, node_id, parent_id, name, type_, size, classification, checksum):
        self.id = node_id
        self.parent_id = parent_id
        self.name = name
        self.type = type_
        # 处理空值:文件大小转整数,目录大小初始为0
        self.size = int(size) if size.strip() else 0
        self.classification = classification.strip() if classification else None
        self.checksum = checksum.strip() if checksum else None
        self.children = []
        self.total_size = 0  # 目录的总大小,文件则等于自身size

def build_tree(csv_data):
    id_to_node = {}
    root_nodes = []
    
    # 第一步:解析所有节点,存入字典
    for line in csv_data.strip().split('\n'):
        parts = line.strip().split(';')
        # 提取字段,注意处理末尾的空分隔符
        node_id = int(parts[0])
        parent_id = int(parts[1]) if parts[1].strip() else None
        name = parts[2]
        type_ = parts[3]
        size = parts[4]
        classification = parts[5]
        checksum = parts[6]
        
        node = Node(node_id, parent_id, name, type_, size, classification, checksum)
        id_to_node[node_id] = node
        
        # 标记根节点
        if parent_id is None:
            root_nodes.append(node)
    
    # 第二步:建立父子关系
    for node in id_to_node.values():
        if node.parent_id is not None and node.parent_id in id_to_node:
            parent_node = id_to_node[node.parent_id]
            parent_node.children.append(node)
    
    # 第三步:递归计算目录总大小
    def calculate_total_size(node):
        if node.type == 'file':
            node.total_size = node.size
            return node.size
        # 目录的总大小是所有子节点的总大小之和
        total = 0
        for child in node.children:
            total += calculate_total_size(child)
        node.total_size = total
        return total
    
    for root in root_nodes:
        calculate_total_size(root)
    
    return root_nodes

def print_tree(nodes, indent=0):
    indent_str = '  ' * indent
    for node in nodes:
        if node.type == 'directory':
            print(f"{indent_str}name = {node.name}, type = Directory, size = {node.total_size}")
            # 递归打印子节点,缩进+1
            print_tree(node.children, indent + 1)
        else:
            print(f"{indent_str}name = {node.name}, type = File, size = {node.size}, classification = {node.classification}, checksum = {node.checksum}")

# 你的CSV数据
csv_content = """1;3;file1;file;10;Secret;42;
2; ;folder2;directory; ; ; ;
3;11;folder3;directory; ; ; ;
4;2;file4;file;40;Secret;42;
5;3;file5;file;50;Public;42;
6;3;file6;file;60;Secret;42;
7;3;file7;file;70;Public;42;
8;10;file8;file;80;Secret;42;
9;10;file9;file;90;Top secret;42;
10;11;folder10;directory; ; ; ;
11;2;folder11;directory; ; ; ;"""

# 构建并打印树形结构
roots = build_tree(csv_content)
print_tree(roots)

输出效果

运行后会输出和你预期一致的层级结构,目录显示总大小,文件显示完整属性,并且按层级缩进。


Java 实现

思路

和Python思路一致,用HashMap存储ID到节点的映射,自定义Node类,递归完成大小计算和打印。

完整代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Node {
    private int id;
    private Integer parentId; // 用Integer存,支持null(根节点)
    private String name;
    private String type;
    private int size;
    private String classification;
    private String checksum;
    private List<Node> children;
    private int totalSize;

    public Node(int id, Integer parentId, String name, String type, int size, String classification, String checksum) {
        this.id = id;
        this.parentId = parentId;
        this.name = name;
        this.type = type;
        this.size = size;
        this.classification = classification;
        this.checksum = checksum;
        this.children = new ArrayList<>();
        this.totalSize = 0;
    }

    // Getter和Setter方法
    public int getId() { return id; }
    public Integer getParentId() { return parentId; }
    public String getName() { return name; }
    public String getType() { return type; }
    public int getSize() { return size; }
    public String getClassification() { return classification; }
    public String getChecksum() { return checksum; }
    public List<Node> getChildren() { return children; }
    public int getTotalSize() { return totalSize; }
    public void setTotalSize(int totalSize) { this.totalSize = totalSize; }
}

public class DirectoryTreeBuilder {
    public static List<Node> buildTree(String csvContent) {
        Map<Integer, Node> idToNode = new HashMap<>();
        List<Node> rootNodes = new ArrayList<>();

        // 解析CSV行
        String[] lines = csvContent.trim().split("\n");
        for (String line : lines) {
            String[] parts = line.trim().split(";");
            int nodeId = Integer.parseInt(parts[0]);
            Integer parentId = parts[1].trim().isEmpty() ? null : Integer.parseInt(parts[1].trim());
            String name = parts[2];
            String type = parts[3];
            int size = parts[4].trim().isEmpty() ? 0 : Integer.parseInt(parts[4].trim());
            String classification = parts[5].trim().isEmpty() ? null : parts[5].trim();
            String checksum = parts[6].trim().isEmpty() ? null : parts[6].trim();

            Node node = new Node(nodeId, parentId, name, type, size, classification, checksum);
            idToNode.put(nodeId, node);

            if (parentId == null) {
                rootNodes.add(node);
            }
        }

        // 建立父子关系
        for (Node node : idToNode.values()) {
            Integer parentId = node.getParentId();
            if (parentId != null && idToNode.containsKey(parentId)) {
                Node parentNode = idToNode.get(parentId);
                parentNode.getChildren().add(node);
            }
        }

        // 计算目录总大小
        calculateTotalSize(rootNodes);

        return rootNodes;
    }

    private static int calculateTotalSize(Node node) {
        if ("file".equals(node.getType())) {
            node.setTotalSize(node.getSize());
            return node.getSize();
        }
        int total = 0;
        for (Node child : node.getChildren()) {
            total += calculateTotalSize(child);
        }
        node.setTotalSize(total);
        return total;
    }

    private static void calculateTotalSize(List<Node> nodes) {
        for (Node node : nodes) {
            calculateTotalSize(node);
        }
    }

    public static void printTree(List<Node> nodes, int indent) {
        String indentStr = "  ".repeat(indent);
        for (Node node : nodes) {
            if ("directory".equals(node.getType())) {
                System.out.printf("%sname = %s, type = Directory, size = %d%n", indentStr, node.getName(), node.getTotalSize());
                printTree(node.getChildren(), indent + 1);
            } else {
                System.out.printf("%sname = %s, type = File, size = %d, classification = %s, checksum = %s%n",
                        indentStr, node.getName(), node.getSize(), node.getClassification(), node.getChecksum());
            }
        }
    }

    public static void main(String[] args) {
        String csvContent = """
                1;3;file1;file;10;Secret;42;
                2; ;folder2;directory; ; ; ;
                3;11;folder3;directory; ; ; ;
                4;2;file4;file;40;Secret;42;
                5;3;file5;file;50;Public;42;
                6;3;file6;file;60;Secret;42;
                7;3;file7;file;70;Public;42;
                8;10;file8;file;80;Secret;42;
                9;10;file9;file;90;Top secret;42;
                10;11;folder10;directory; ; ; ;
                11;2;folder11;directory; ; ; ;""";

        List<Node> roots = buildTree(csvContent);
        printTree(roots, 0);
    }
}

说明

Java版本同样会生成符合要求的树形输出,注意处理了CSV中的空值(比如空的parentId转为null作为根节点,空的size转为0),递归逻辑和Python完全对应。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:13