正则表达式,从分隔字符串中删除重复路径

Tro*_*ter 7 c# regex perl

我正在尝试使用正则表达式从分号分隔的字符串中删除重复的文件路径.最终路径的顺序无关紧要.

示例输入:

C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path5;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path6;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;
Run Code Online (Sandbox Code Playgroud)

期望的输出:

C:\Users\user\Desktop\TESTING\path5;C:\Users\user\Desktop\TESTING\path6;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;
Run Code Online (Sandbox Code Playgroud)

我有以下正则表达式,但是当输入字符串变得很长时非常慢.添加到这个运行它数千行,时间是非常糟糕的.

\b([^;]+)(?=.*;\1;);
Run Code Online (Sandbox Code Playgroud)

任何有关如何提高性能的提示都非常感谢!

Pat*_*ner 8

或者C#版本:

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var paths = @"C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path5;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path6;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;";

        var cleaned = string.Join(";", new HashSet<string>(paths.Split(';')));

        Console.WriteLine(cleaned);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path5;C:\Users\user\Desktop\TESTING\path6;C:\Users\user\Desktop\TESTING\path3;
Run Code Online (Sandbox Code Playgroud)

拆分输入;,使其成为一个HashSet<string>(..)摆脱欺骗,;再次加入.


警告:如果您的路径包含;作为目录名称的一部分,则会中断 - 您必须为该案例获得更多创意 - 但同样适用于您使用的任何RegEx.


hau*_*kex 7

在Perl中删除重复项的典型方法是使用哈希.另请参见perlfaq4:如何从列表或数组中删除重复的元素?

my $str = q{C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path5;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path6;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3};
my %seen;
my $out = join ';', sort grep { !$seen{$_}++ } split /;/, $str;
print $out, "\n";
__END__
# Output:
C:\Users\user\Desktop\TESTING\path1;C:\Users\user\Desktop\TESTING\path3;C:\Users\user\Desktop\TESTING\path5;C:\Users\user\Desktop\TESTING\path6
Run Code Online (Sandbox Code Playgroud)

我把它扔进sort那里,但你可以删除它,如果你不需要它.

虽然您尚未指定实现是否应该在C#或Perl中,但同样的想法也应该适用于C#.(更新:Patrick Artner的回答)

请注意,正则表达式很慢,因为对于每个匹配\b([^;]+),引擎必须扫描字符串的其余部分以进行前瞻.*;\1;,因此它基本上就像嵌套循环一样.