【问题标题】:Get common root of String path and list of folders for that path获取字符串路径的公共根目录和该路径的文件夹列表
【发布时间】:2012-06-06 09:06:41
【问题描述】:

我有一个 SQLite3 数据库表,其中存储了如下路径列表:

/mnt/sdcard/folder1/a/b/file1
/mnt/sdcard/folder1/a/b/file2
/mnt/sdcard/folder1/a/b/file3
/mnt/sdcard/folder1/a/b/file4
/mnt/sdcard/folder1/a/b/file5
/mnt/sdcard/folder1/e/c/file6
/mnt/sdcard/folder2/d/file7
/mnt/sdcard/folder2/d/file8
/mnt/sdcard/file9

我要做的是找到这些路径的公共根目录并获取该公共根目录的第一级文件夹(唯一)的列表。

例如

第一次运行:parent root = null(这是第一次运行) 公共根目录 -> /mnt/sdcard/ 文件夹列表 - 文件夹1 - 文件夹2

第二次运行(现在父根目录将是 /mnt/sdcard/folder1/) 公共根 -> /mnt/sdcard/folder1/(与父根相同) 文件夹列表 - 一种 -e

第二次运行(现在父根目录将是 /mnt/sdcard/folder1/a/) 公共根 -> /mnt/sdcard/folder1/a/b(与父根相同) 文件夹列表 -> 空(我会得到文件)

有没有办法通过 db 执行这些过滤器,或者我必须通过代码来执行这些过滤器?

之所以提出这个问题,是因为我需要提供一个 Android 音乐库的文件夹视图来存储歌曲数据库记录中的路径。

【问题讨论】:

    标签: java android sql sqlite


    【解决方案1】:

    看看http://rosettacode.org/wiki/Find_common_directory_path

    它在某些编程语言中实现。

    这是我测试并用于我的目的的 Java 示例。

    public class CommonPath {
        public static String commonPath(String... paths){
            String commonPath = "";
            String[][] folders = new String[paths.length][];
            for(int i = 0; i < paths.length; i++){
                folders[i] = paths[i].split("/"); //split on file separator
            }
            for(int j = 0; j < folders[0].length; j++){
                String thisFolder = folders[0][j]; //grab the next folder name in the first path
                boolean allMatched = true; //assume all have matched in case there are no more paths
                for(int i = 1; i < folders.length && allMatched; i++){ //look at the other paths
                    if(folders[i].length < j){ //if there is no folder here
                        allMatched = false; //no match
                        break; //stop looking because we've gone as far as we can
                    }
                    //otherwise
                    allMatched &= folders[i][j].equals(thisFolder); //check if it matched
                }
                if(allMatched){ //if they all matched this folder name
                    commonPath += thisFolder + "/"; //add it to the answer
                }else{//otherwise
                    break;//stop looking
                }
            }
            return commonPath;
        }
    
        public static void main(String[] args){
            String[] paths = { "/home/user1/tmp/coverage/test",
                     "/home/user1/tmp/covert/operator",
                     "/home/user1/tmp/coven/members"};
            System.out.println(commonPath(paths));
    
            String[] paths2 = { "/hame/user1/tmp/coverage/test",
                     "/home/user1/tmp/covert/operator",
                     "/home/user1/tmp/coven/members"};
            System.out.println(commonPath(paths2));
        }
    }
    

    【讨论】:

    • 您能否简要概述一下为什么该链接特别适用于这个问题?该链接可能会失效,然后您的回答将不再有用...
    • 当然,@der_michael,我发现这个线程正在搜索相同的问题,因为我认为应该实现该算法并将其发布在任何地方。我用来自 rosettacode wiki 的 Java 示例更新了我的答案。
    【解决方案2】:

    我只需要做同样的事情,但在 C# 中。这是我找到公共根目录的解决方案。你应该能够适应它。

            public static string GetCommonRoot( params string[] paths )
        {
            int minDepth = 999;
            List<string[]> parsedPaths = new List<string[]>();
            foreach( string p in paths )
            {
                string[] parts = p.Split( '\\' );
                parsedPaths.Add( parts );
                minDepth = parts.Length < minDepth ? parts.Length : minDepth;
            }
    
            StringBuilder sb = new StringBuilder();
            for( int i = 0; i < minDepth; i++ )
            {
                List<string> tmp = new List<string>();
                foreach( string[] dir in parsedPaths )
                {
                    tmp.Add( dir[ i ].ToLower() );
                }
    
                if( !AllEqual( tmp.ToArray() ) )
                    break;
    
                sb.AppendFormat( "{0}\\", tmp[ 0 ] );
            }
    
            return sb.ToString();
    
        }
    
        private static bool AllEqual( params string[] strings )
        {
            bool rv = true;
            for( int i = 1; i < strings.Length; i++ )
                rv &= strings[ 0 ] == strings[ i ];
    
            return rv;
        }
    

    【讨论】:

      【解决方案3】:

      你应该通过代码来做。
      我们这里需要树形数据结构。 让我们创建类文件夹

      Folder{
       List<String> fileList;
       List<Folder> folderList;
      
      }
      

      现在算法:
      1.获取List pathList中的路径列表

      2. 用分隔符“/”分割列表中的第一个字符串。您将获得字符串数组,例如 array1 该数组中的第一个元素将是根文件夹的名称。创建根文件夹。数组中的下一个元素将是子文件夹。最后一个元素是文件名

      3.对于 pathList 中的剩余路径。分割每条路径。你会得到数组,比如array2。现在并行迭代array1和array2,直到你找到array1 [i]!=array2 [i]。

      如果发现不等式,并且你是array2的最后一个元素,这意味着它的文件在现有文件夹中。将其添加到列表中。如果您不是最后一个元素,则需要创建文件夹。 这将创建文件夹树。

      【讨论】:

      • 我不想查询文件系统。我在数据库中有一个路径列表,我想找到一个算法来获取我在问题中提出的信息:) 我已经制定了“文件系统解决方案”并且它没有优化
      • 明天试一试,希望5k以上歌曲不会太重
      • 它可能会变得很重。如果您确定路径将始终按排序顺序排列,您可以尝试一些优化技术。
      • 我也在想,也许一个好的解决方案是使用一个树来实现节点是文件夹和叶子是文件(歌曲)的结构
      • 如果你观察到,这个算法只是创建树状结构。只是我们没有将它命名为树。这里文件夹是节点,文件是叶子。所选文件夹中可以有多个文件夹和文件,因此我们对两者都使用列表。
      【解决方案4】:

      开源Java库path-pattern-finder提供了查找路径公共目录根的功能。

      import com.owenfeehan.pathpatternfinder.commonpath.FindCommonPathElements;
      Optional<Path> commonPath = FindCommonPathElements.findForFilePaths(paths);
      

      它还可以更广泛地用于在路径中查找某些命名模式(数字序列、常量子字符串等)。

      完全披露:我是图书馆的作者。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-05
        • 2013-05-08
        • 1970-01-01
        • 1970-01-01
        • 2020-04-14
        • 2017-01-29
        • 2021-02-05
        • 1970-01-01
        相关资源
        最近更新 更多