从java中的字符串列表中提取公共前缀

时间:2013-07-02 10:35:46

标签: java regex

我想在java中做类似的事情(extracting the common prefixes from a list of strings)。字符串列表是文件路径 Eg: List filePaths1 = new ArrayList();
filePaths1.add("/root/test1/asass");
filePaths1.add("/root/test1");
filePaths1.add("/root/test");
filePaths1.add("/root/test/aaa/");
filePaths1.add("/root/test/bbb/ccc
");
filePaths1.add("/root/test/fff/");
filePaths1.add("/root/test/eee/asasa/
");
filePaths1.add("/root/rahul/e?ee/asasa/");
filePaths1.add("/root/rahul/asasa/
");
filePaths1.add("/root/rahul/no*tthis/asasa/**");
filePaths1.add("/etc/rahul/test");

想要实现一个函数,如果我们将上面的列表传递给它,它将返回以下字符串的列表。

{"/root/test1", "/root/test", "/root/rahul", "/etc/rahul/test"}

它应该将每个字符串与另一个字符串进行比较,在上面的情况 如果我们考虑2个字符串“/ root / test1 / asass”和“/ root / test1”,它有最长的公共前缀为/ root / test1,所以我们将它添加到输出列表,如果有任何其他字符串正在启动使用/ root / test1,它将由/ r​​oot / test1表示。

由于有五个字符串以/ root / test开头,因此输出列表将包含/ root / test,因为这5个字符串的最长公共前缀为“/ root / test”。

同样,只有1个字符串具有模式/ etc / rahul / test,它不共享或以定义的任何其他模式开始,因此它将按原样添加,

我们可以使用正则表达式吗?任何建议都会非常有用。如果需要任何其他信息,请告诉我。

2 个答案:

答案 0 :(得分:1)

描述

如果我理解正确,您正在寻找一种方法来识别列表中每个文件夹的最大公分母。我看到你提供了一个很大的文件夹列表,你想筛选所有条目,只返回最大的。额外的处理逻辑超出了这个表达式的范围。

所以给出:

/root/test1/aaaaa
/root/test2/bbbbb
/root/test3/ccccc

您希望/root/成为所有条目的公共文件夹。

鉴于:

/root/test1/aaaaa
/root/test1/bbbbb
/root/test1/ccccc

您希望/root/test1/成为常用文件夹。

此正则表达式将在上面的示例中找到那些最大的分母。您可以使用它来遍历所有值,匹配它们并根据您所需的逻辑构建结果数组。

^(\/.*(?=[\/\n\r])).*[\r\n]*(?:^(?=\1).*?[\r\n]*)*\Z

enter image description here

注意:我正在使用不区分大小写的选项来保持示例简单,如果在* nix系统上运行,则需要删除它,以区分文件级别的大写和小写。同样使用此表达式需要多行选项,例如:

Pattern re = Pattern.compile("^(\\/.*(?=[\\/\\n\\r])).*[\\r\\n]*(?:^(?=\\1).*?[\\r\\n]*)*\\Z",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
OP中

不清除

不清楚的是你想如何处理如下列表:

/root/test1/test2/test3/aaaaa
/root/test1/test2/bbbbb
/root/test1/ccccc

答案 1 :(得分:1)

描述

在查看详细的聊天窗口后,我看到你有来自M Buettner的示例文本:

(diverging at level 1) 
/root/abc/foo 
/etc/def/bar 
would give two entries 

(diverging at level 2) 
/root/abc/foo 
/root/def/foo 
would give two entries 

(diverging at level 3 and beyond) 
but 
/root/abc/def/ghi 
/root/abc/klm/nop 
would give only one entry? (/root/abc/)

看起来你想要从字符串的开头到第三个/

的每个唯一字符串

这个powershell [抱歉我不太了解java]确实返回了唯一值。

$folders = New-Object System.Collections.ArrayList
$null = $folders.add("/root/test1/asass")
$null = $folders.add("/root/test1")
$null = $folders.add("/root/test")
$null = $folders.add("/root/test/aaa")
$null = $folders.add("/root/test/bbb/ccc")
$null = $folders.add("/root/test/fff")
$null = $folders.add("/root/test/eee")
$null = $folders.add("/root/rahul/e?ee/aaaaa")
$null = $folders.add("/root/rahul/aaa")
$null = $folders.add("/root/rahul/no*tthis/aaaaa")
$null = $folders.add("/root/rahul/test")
$null = $folders.add("/etc/rahul/test")

Write-Host "------"

$Output = New-Object System.Collections.ArrayList
foreach ($folder in $folders) {
    [regex]::Match($folder, "^(\/(?:.*?(?:\/|$)){0,2})", "Multiline") | foreach {
        # found a match set
        $null = $Output.add($_.Groups[1].Value)
        } # next match
    } # next folder


$Output | select -unique

<强>返回

/root/test1/
/root/test1
/root/test
/root/test/
/root/rahul/
/etc/rahul/