Как сопоставить эту строку с Regex? - PullRequest
0 голосов
/ 09 августа 2009

В основном у меня есть музыкальные имена, такие как:

<source> <target>

"Travis - Sing"   "Travis - Sing 2001.mp3"
"Travis - Sing"   "Travis - Sing Edit.mp3"
"Travis - Sing"   "Travis - Sing New Edit.mp3"
"Mission Impossible I"   "Mission Impossible I - Main Theme.mp3"
"Mission Impossible I"   "Mission Impossible II - Main Theme.mp3"
"Mesrine - Death Instinct"   "Mesrine - Death Instinct - Le Million.mp3"
"Mesrine - Public Enemy #1"   "Mesrine - Public Enemy #1 - Theme"
"Se7en"   "Se7en Motion Picture Soundtrack - Theme.mp3"

Скобки не включены в строки (только для демонстрации).

и я пытаюсь сопоставить «исходные» и «целевые» значения.

Так что имена источников у меня уже есть, но сейчас я использую много разборов строк, чтобы иметь возможность сопоставить их. Как я могу добиться того же, используя Regex?

РЕДАКТИРОВАТЬ: Кажется, что есть путаница.

"Travis - Sing" - моя исходная строка, и я пытаюсь сопоставить ее с:

"Travis - Sing (2001).mp3"
"Travis - Sing (Edit).mp3"
"Travis - Sing (New Edit).mp3"

EDIT2: убрана скобка.

Ответы [ 4 ]

3 голосов
/ 09 августа 2009

Кажется, вы ищете все файлы, которые начинаются с определенной строки - это ответит на все ваши примеры. Это может быть легко достигнуто без регулярных выражений с использованием двух циклов или с помощью linq:

var matches = from source in sources
              select new
                      {
                          Source = source,
                          Targets = from file in targets
                                    where file.StartsWith(source)
                                    select file
                      };

Вы также можете использовать регулярное выражение вместо условия StartsWith, например:

where Regex.IsMatch(file, String.Format("^{0}", source), RegexOptions.IgnoreCase)

Вероятно, это можно оптимизировать многими способами, но Эндрю предлагает написать длинный шаблон, который не выполняется быстрее при динамическом выполнении.

2 голосов
/ 09 августа 2009

Из вашего ответа на мой комментарий я уверен, что вы ищете что-то простое, как это.

Таким образом, вы можете иметь несколько поисковых терминов, разделенных "|". Это альтернативная конструкция .

class Program
{
    private static List<string> searchList = new List<string>
                                     {
                                         "Travis - Sing (2001).mp3",
                                         "Travis - Sing (Edit).mp3",
                                         "Mission Impossible I - Main Theme.mp3",
                                         "Mission Impossible II - Main Theme.mp3",
                                         "doesn't match"
                                     };

    static void Main(string[] args)
    {
        var matchRegex = new Regex("Travis - Sing|Mission Impossible I");
        var matchingStrings = searchList.Where(str => matchRegex.IsMatch(str));

        foreach (var str in matchingStrings)
        {
            Console.WriteLine(str);
        }
    }
}

EDIT Если вы хотите узнать, против чего вы подходите, вы можете добавить groups :

    static void Main(string[] args)
    {
        var matchRegex = new Regex("(?<travis>Travis - Sing)|(?<mi>Mission Impossible I)");

        foreach (var str in searchList)
        {
            var match = matchRegex.Match(str);
            if (match.Success)
            {
                if (match.Groups["travis"].Success)
                {
                    Console.WriteLine(String.Format("{0} matches against travis", str));
                }
                else if (match.Groups["mi"].Success)
                {
                    Console.WriteLine(String.Format("{0} matches against mi", str));
                }
            }
        }
    }
1 голос
/ 09 августа 2009

Следующий метод немного более надежен (допускает различное количество пробелов или разрывов между источником и целью). Например. цель может иметь дополнительные пробелы между словами, но она все равно будет совпадать.

Сначала определите символы, которые разрешены в качестве разделителей слов в вашей строке. Затем разделите исходную и целевую строки на токены, используя разделители. Затем проверьте, не найдены ли слова в вашем источнике в качестве начальных слов.

например. (Java) Я использовал пробелы и дефисы в качестве разделителей

public boolean isValidMatch(String source, String target){
    String[] sourceTokens = source.split("[\\s\\-]+");  // split on sequence of 
    //whitespaces or dashes. Two dashes between words will still split 
    //same as one dash.

    String[] targetTokens = target.split("[\\s\\-]+"); // split similarly
    if(sourceTokens.length>targetTokens.length){
        return false;
    }

    for(int i=0;i<souceTokens.length;i++){
        if(!sourceTokens[i].equals(targetTokens[i])){
            return false;
        }
    }
    return true;
}

PS: Вы можете добавить точку "." символ в качестве разделителя, если у вас есть источник "Hello World" и цель "Hello World.mp3"; В настоящее время он не будет совпадать, поскольку регулярное выражение не разбивается на точки, но если вы расширите свой разделитель, включив в него точку, то оно будет.

1 голос
/ 09 августа 2009

Всегда ли есть несколько пробелов между источником и целью? Если это так, то будет соответствовать следующее:

/^(.*?)\s{2,}(.*?)$/

Он в основном соответствует двум элементам, один до любого пробела в 2+ пробела, и один после этого пробела. (В шаблонах захвата используется не жадный .*?, поэтому, если имеется более 2 пробелов, лишние пробелы также не будут захвачены.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...