实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型

实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型

申明

首先说明一下,这是一道面试题。介于时间关系这道题只能算是解决了一半。

一、问题描述

        //实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
        //输入
        List<String> pathList = Arrays.asList(
                "/etc/hosts",
                "/etc/kubernetes/ssl/certs",
                "/root"
        );
        //输出
/**
         {
            "etc":{
                "hosts":{},
                "kubernetes":{
                    "ssl":{
                        "certs":{}
                    }
                }
            },
            "root":{}
         }

二、实现思路

1、按照每一行的路径记录 / 的位置,得到一个二维数组。
统计一行中字符串中 / 的位置 ,得到一维数组。

    //统计一行字符串中 / 的位置
    private static List<Integer> countNum(String path){
        List<Integer> rowCount = new ArrayList<Integer>() ;
        if (!path.isEmpty()){
            char[] chars = path.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '/'){
                    rowCount.add(i);
                }
            }
        }
        return rowCount;
    }

统计多行字符串中 / 的位置 ,得到二维数组。

            //统计 有多少行 字符串 包含 多少个list(list存放 / 在字符数组中的位置)
            List<List<Integer>> colCount = new ArrayList<List<Integer>>();
            for (int i = 0; i < pathList.size(); i++) {
                List<Integer> rowCount = countNum(pathList.get(i));
                Map<String, Map> rowElementMap = rowElementMap(pathList.get(i));
                mapList.add(rowElementMap);
                colCount.add(rowCount);
            }

2、由第1步的 / 位置 数组 进行字符串递归截串,注意 /root 这种情况即可。
这里解释下为什么递归:

                "/etc/hosts",
                "/etc/kubernetes/ssl/certs",
                "/root"

每一个路径都可以看成是 /文件夹名称 这种问题处理。
截串形式为:
/etc/kubernetes/ssl/certs
/kubernetes/ssl/certs
/ssl/certs
/certs
因此,每次需要重新获取path

            int right = rowCount.get(1);
            String pathTemp = path.substring(right);

递归实现

    private static Map<String, Map> rowElementMap(String path){
        List<Integer> rowCount = countNum(path);
        int left = rowCount.get(0)+1;
        if (rowCount.size() == 1){
            String rowKey = path.substring(left);
            HashMap<String, Map> rowMap = new HashMap<>();
            rowMap.put(rowKey, new HashMap());
            return rowMap;
        }else {
            int right = rowCount.get(1);
            String rowKey = path.substring(left, right);
            String pathTemp = path.substring(right);
            HashMap<String, Map> rowMap = new HashMap<>();
            //注意这里的value,递归获取map
            rowMap.put(rowKey, rowElementMap(pathTemp));
            return rowMap;
        }
    }

三、源码

方法一、返回单个map的源代码

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.util.*;

/**
 * @Description:
 * @Author: AustinU
 * @CreateTime: 2022/8/18
 */
public class Main {
    public static void main(String[] args) {
        //实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
        List<String> pathList = Arrays.asList(
                "/etc/hosts",
                "/root",
                "/etc/kubernetes/ssl/certs"
        );
        /**
         {
            "etc":{
                "hosts":{},
                "kubernetes":{
                    "ssl":{
                        "certs":{}
                    }
                }
            },
            "root":{}
         }
         */
        Map<String, Map> resultMap = pathListToMap(pathList);
        System.out.println(resultMap);
        JSONObject jsonObject = JSONUtil.parseObj(resultMap);
        System.out.println(jsonObject);

    }

    private static Map<String, Map> pathListToMap(List<String> pathList) {
        if (pathList.isEmpty()) return null;
        if (pathList.size() == 1 && countNum(pathList.get(0)).size() == 1) {
            String resKey = pathList.get(0).replaceAll("\\/", "");
            HashMap<String,Map> resMap = new HashMap<String, Map>();
            resMap.put(resKey, new HashMap<String,Map>());
            return resMap;
        }else {
            List<Map<String, Map>> mapList= new ArrayList<>();
            //统计 有多少列 字符串 包含 多少个list(list存放 / 在字符数组中的位置)
            List<List<Integer>> colCount = new ArrayList<List<Integer>>();
            for (int i = 0; i < pathList.size(); i++) {
                List<Integer> rowCount = countNum(pathList.get(i));
                Map<String, Map> rowElementMap = rowElementMap(pathList.get(i));
                mapList.add(rowElementMap);
                colCount.add(rowCount);
            }
            Map<String, Map> resMap = mapList2OneMap(mapList);
            return resMap;
        }

    }

    //将多行map合并成同一个map
    private static Map<String, Map> mapList2OneMap(List<Map<String, Map>> mapList) {
        HashMap<String,Map> resMap = new HashMap<>();
        HashMap<String,List<Map<String, Map>>> resListMap = new HashMap<>();
        List<Map<String, Map>> resMapList = new ArrayList<>();
        if (mapList.isEmpty()) return new HashMap<String, Map>();
        if (mapList.size() == 1) return mapList.get(0);
        else {
            for (int i = 0; i < mapList.size(); i++) {
                resMap.putAll(mapList.get(i));
            }
            return resMap;
        }
    }

    //统计字符串中 / 的位置
    private static List<Integer> countNum(String path){
        List<Integer> rowCount = new ArrayList<Integer>() ;
        if (!path.isEmpty()){
            char[] chars = path.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '/'){
                    rowCount.add(i);
                }
            }
        }
        return rowCount;
    }


    private static Map<String, Map> rowElementMap(String path){
        List<Integer> rowCount = countNum(path);
        int left = rowCount.get(0)+1;
        if (rowCount.size() == 1){
            String rowKey = path.substring(left);
            HashMap<String, Map> rowMap = new HashMap<>();
            rowMap.put(rowKey, new HashMap());
            return rowMap;
        }else {
            int right = rowCount.get(1);
            String rowKey = path.substring(left, right);
            String pathTemp = path.substring(right);
            HashMap<String, Map> rowMap = new HashMap<>();
            rowMap.put(rowKey, rowElementMap(pathTemp));
            return rowMap;
        }
    }

}

输出结果:
在这里插入图片描述
运行结果放在JSON可视化工具展现如下
在这里插入图片描述
和期望结果对比可知,如果map中首次放入的key相同会存在覆盖value的情况。

方法二、返回map的列表的源代码

package ruiqi;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.util.*;

/**
 * @Description:
 * @Author: AustinU
 * @CreateTime: 2022/8/18
 */
public class MainReturnMapList {
    public static void main(String[] args) {
        //实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
        List<String> pathList = Arrays.asList(
                "/etc/hosts",
                "/etc/kubernetes/ssl/certs",
                "/root"
        );
        /**
         {
            "etc":{
                "hosts":{},
                "kubernetes":{
                    "ssl":{
                        "certs":{}
                    }
                }
            },
            "root":{}
         }
         */
        Map<String, List<Map<String, Map>>> resultMap = pathListToMap(pathList);
        System.out.println(resultMap);
        JSONObject jsonObject = JSONUtil.parseObj(resultMap);
        System.out.println(jsonObject);

    }

    private static Map<String, List<Map<String, Map>>> pathListToMap(List<String> pathList) {
        if (pathList.isEmpty()) return null;
        if (pathList.size() == 1 && countNum(pathList.get(0)).size() == 1) {
            String resKey = pathList.get(0).replaceAll("\\/", "");
            HashMap<String,Map> resMap = new HashMap<String, Map>();
            resMap.put(resKey, new HashMap<String,Map>());
            List<Map<String, Map>> mapList = new ArrayList<>();
            mapList.add(resMap);
            Map<String, List<Map<String, Map>>> resMapList = new HashMap<>();
            resMapList.put(resKey, mapList);
            return resMapList;
        }else {
            List<Map<String, Map>> mapList= new ArrayList<>();
            int n = pathList.size();
            //统计 有多少列 字符串 包含 多少个list(list存放 / 在字符数组中的位置)
            List<List<Integer>> colCount = new ArrayList<List<Integer>>();
            for (int i = 0; i < pathList.size(); i++) {
                List<Integer> rowCount = countNum(pathList.get(i));
                Map<String, Map> rowElementMap = rowElementMap(pathList.get(i));
                mapList.add(rowElementMap);
                colCount.add(rowCount);
            }
            Map<String, List<Map<String, Map>>> resMap = mapList2OneMap(mapList);
            return resMap;
        }

    }

    //将多行map合并成同一个map
    private static Map<String, List<Map<String, Map>>> mapList2OneMap(List<Map<String, Map>> mapList) {
        HashMap<String,Map> resMap = new HashMap<>();
        HashMap<String,List<Map<String, Map>>> resListMap = new HashMap<>();
        List<Map<String, Map>> resMapList = new ArrayList<>();
        if (mapList.isEmpty()) return new HashMap<String, List<Map<String, Map>>>();
        else {
            for (int i = 0; i < mapList.size(); i++) {
                for (Map.Entry<String, Map> mapEntry : mapList.get(i).entrySet()) {

                    if (!resMap.containsKey(mapEntry.getKey())){
                        resMapList.add(mapEntry.getValue());
                        resListMap.put(mapEntry.getKey(), resMapList);
                    }else {
                        //具有相同key
                        resMapList.add(mapEntry.getValue());
                    }
                }
            }
            return resListMap;
        }
    }
    
    //统计字符串中 有几个 /
    private static List<Integer> countNum(String path){
        List<Integer> rowCount = new ArrayList<Integer>() ;
        if (!path.isEmpty()){
            char[] chars = path.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '/'){
                    rowCount.add(i);
                }
            }
        }
        return rowCount;
    }

    private static Map<String, Map> rowElementMap(String path){
        List<Integer> rowCount = countNum(path);
        int left = rowCount.get(0)+1;
        if (rowCount.size() == 1){
            String rowKey = path.substring(left);
            HashMap<String, Map> rowMap = new HashMap<>();
            rowMap.put(rowKey, new HashMap());
            return rowMap;
        }else {
            int right = rowCount.get(1);
            String rowKey = path.substring(left, right);
            String pathList = path.substring(right);
            HashMap<String, Map> rowMap = new HashMap<>();
            rowMap.put(rowKey, rowElementMap(pathList));
            return rowMap;
        }
    }

}

输出结果:
在这里插入图片描述
运行结果放在JSON可视化工具展现如下
在这里插入图片描述
这里存在的问题是节点信息存在无中生有。
如果大家对 这道题有见解欢迎留言。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将绝对路径转换为能供QAbstractItemModel使用的QModelIndex类型,需要通过QModelIndex的createIndex()方法创建一个索引,该方法有以下参数: 1. 行号(row):该索引在模型中的行号。 2. 列号(column):该索引在模型中的列号。 3. 数据指针(ptr):该索引所对应的数据指针。可以是任意类型的指针,通常是指向该索引对应的数据对象的指针。 4. 父索引(parent):该索引的父级索引。 因此,要将绝对路径转换为QModelIndex类型,需要按照以下步骤进行: 1. 将绝对路径拆分为路径和文件名两部分。 2. 在模型中查找路径所对应的索引,如果不存在则创建该索引。 3. 在路径所对应的索引下查找文件名所对应的索引,如果不存在则创建该索引。 4. 将文件名所对应的索引作为最终索引,使用createIndex()方法创建QModelIndex对象。 以下是一个示例代码,其将一个绝对路径转换为QModelIndex类型: ```cpp QModelIndex index = QModelIndex(); // 根索引 QStringList pathList = path.split("/"); // 将路径拆分为路径列表 foreach (QString subdir, pathList) { int row = index.row(); int column = 0; // 假设是单列模型 QModelIndex childIndex = index.child(row, column); bool found = false; for (int i = 0; i < model->rowCount(index); i++) { QModelIndex child = index.child(i, column); if (child.data().toString() == subdir) { childIndex = child; found = true; break; } } if (!found) { childIndex = model->index(row, column, index); model->insertRow(row, index); model->setData(childIndex, subdir); } index = childIndex; } // 使用文件名创建最终索引 int row = index.row(); int column = 0; // 假设是单列模型 QModelIndex finalIndex = model->createIndex(row, column, nullptr); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值