如何识别和删除文件夹列表中的子文件夹?

时间:2017-01-14 18:05:26

标签: arrays algorithm

我们说我有一个数组中的文件夹列表:

c:\aaa\bbb
d:\aaa\bbb
c:\aaa\bbb\ccc
c:\aaa\bbb\ccc\ddd

我的程序将以递归方式对这些文件夹中的每个对象执行一些操作。但正如您所看到的,此数组中的某些文件夹具有父子关系。所以我应该在进程之前删除此数组中的嵌套文件夹。对于上面的示例,c:\aaa\bbb\ccc\dddc:\aaa\bbb\ccc将被移除,因为它们嵌套在c:\aaa\bbb中。最好的方法是什么?

2 个答案:

答案 0 :(得分:0)

我不知道这是否是解决问题的最佳方法,但在此过程中找到它是一些明智之处。

首先,代码

/**
 * Created by Zack at 14/January/2017
 */
public class ChildPathRemover {

    private final Node mRoot = new Node();

    /**
     *
     * @param path
     * @return True if the directory was added, False if is a child directory
     */
    public boolean add(String path) {
        Node currNode = mRoot;

        String[] parts = path.split(Pattern.quote(File.separator));
        for (int i = 0; i < parts.length; i++) {
            // contains
            Node nextNode = currNode.subNodes.get(parts[i]);

            if (nextNode != null) {
                // Already has a parent
                if (nextNode.isLeaf) {
                    return false;
                } // Process the nextNode
                else {
                    currNode = nextNode;
                }
            } // Reached the end, so we a good to add new path
            else {
                for (int k = i; k < parts.length; k++) {
                    Node newNode = new Node();
                    currNode.subNodes.put(parts[k], newNode);
                    currNode = newNode;
                }

                currNode.isLeaf = true;
                break;
            }
        }

        // TODO: if the parent were not added first, you will need to rebuild the paths, based on the
        // Nodes and then call the Remove Listener

        return true;
    }

    private static class Node {

        boolean isLeaf = false;
        HashMap<String, Node> subNodes = new HashMap<>();
    }

    public interface RemoveListener {

        void pathRemoved(String path);
    }

    /**
     * Call this method to remove the child paths
     *
     * @param paths
     */
    public static void removeChildPath(List<String> paths) {
        // Sort by the length of the path
        Collections.sort(paths, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return Integer.compare(o1.length(), o2.length());
            }
        });


        ChildPathRemover cpr = new ChildPathRemover();

        Iterator<String> itr = paths.iterator();
        while (itr.hasNext()) {
            if (!cpr.add(itr.next())) {
                itr.remove();
            }
        }
    }
}

如何使用的示例。

public static void main(String[] args) {
    ArrayList<String> paths = new ArrayList<>();
    paths.add("d:\\aaa\\bbb");
    paths.add("c:\\aaa\\bbb\\ccc");
    paths.add("c:\\aaa\\bbb\\ccc\\ddd");
    paths.add("c:\\aaa\\bbb");

    removeChildPath(paths);

    for (String path : paths) {
        System.out.println("path = " + path);
    }
}

此示例将生成

path = d:\aaa\bbb
path = c:\aaa\bbb

<强>解释

这里的想法是模拟一棵树。

首先我们添加所有父文件夹;这是通过按路径长度对数组进行排序来完成的。

然后,每次我们添加成功的路径时,它都会被标记为叶子。当我们尝试添加另一个路径并且它“更大”时,代码将知道它是一个孩子,所以我们删除它。

编辑:

抱歉......我没有看到这个问题是标记为Java问题......

答案 1 :(得分:0)

您可以先按升序对数组进行排序,然后按顺序访问每个文件夹。然后跟踪父母&#34;文件夹,以无效名称开头:

 sort folders
 parent = '>'
 result = []
 for each folder in folders:  
     if folder does not start with parent followed by a slash: 
         # keep folder, and remember it as potential parent
         append folder to result
         parent = folder

这是一个JavaScript代码示例:

&#13;
&#13;
var folders = [
    'c:\\aaa\\bbb',
    'd:\\aaa\\bbb',
    'c:\\aaa\\bbb\\ccc',
    'c:\\aaa\\bbb\\ccc\\ddd'
];

folders.sort();
let parent = '>';
let result = [];
for (var i = 0; i < folders.length; i++) {
    if (folders[i].indexOf(parent + '\\') != 0) {
        result.push(folders[i]); // keep it
        parent = folders[i]; // and remember this as potential parent 
    }
}

// Display result
console.log(result.join('\n'));
&#13;
&#13;
&#13;

相关问题