Разделить строку с различными условиями, используя Linq в C # - PullRequest
0 голосов
/ 11 марта 2011

Мне нужно извлечь и удалить слово из строки. Слово должно быть в верхнем регистре и должно следовать за одним из разделителей /, ;, (, - или пробелом.

Некоторые примеры:

  1. "this is test A/ABC"
    Ожидаемый результат: "this is test A" и "ABC"

  2. "this is a test; ABC/XYZ"
    Ожидаемый результат: "this is a test; ABC" и "XYZ"

  3. "This TASK is assigned to ANIL/SHAM in our project"
    Ожидаемый результат: "This TASK is assigned to ANIL in our project" и "SHAM"

  4. "This TASK is assigned to ANIL/SHAM in OUR project"
    Ожидаемый результат: "This TASK is assigned to ANIL/SHAM in project" и "OUR"

  5. "this is test AWN.A"
    Ожидаемый результат: "this is test" и "AWN.A"

  6. "XETRA-DAX" Ожидаемый результат: "XETRA" и "DAX"

  7. "FTSE-100" Ожидаемый результат: "-100" и "FTSE"

  8. "ATHEX" Ожидаемый результат: "" и "ATHEX"

  9. "Euro-Stoxx-50" Ожидаемый результат: "Euro-Stoxx-50" и ""

Как мне этого добиться?

Ответы [ 5 ]

14 голосов
/ 11 марта 2011

«Умная» версия:

    string strValue = "this is test A/ABC";
    int ix = strValue.LastIndexOfAny(new[] { '/', ' ', ';', '(', '-' });
    var str1 = strValue.Substring(0, ix);
    var str2 = strValue.Substring(ix + 1);

Версия "тупой LINQ":

    var str3 = new string(strValue.Reverse().SkipWhile(p => p != '/' && p != ' ' && p != ';' && p != '(' && p != '-').Skip(1).Reverse().ToArray());
    var str4 = new string(strValue.Reverse().TakeWhile(p => p != '/' && p != ' ' && p != ';' && p != '(' && p != '-').Reverse().ToArray());

оба случая БЕЗ проверок. ОП может добавить проверки, если он хочет их.

По второму вопросу использование LINQ действительно очень сложно. С Regex это "легко выполнимо".

var regex = new Regex("^(.*[A-Z]+)([-/ ;(]+)([A-Z]+)(.*?)$");

var strValueWithout = regex.Replace(strValue, "$1$4");
var extractedPart = regex.Replace(strValue, "$3");

За третий вопрос

var regex = new Regex("^(.*?)([A-Z.]*)([-/ ;(]+)([A-Z.]+)(.*?)$", RegexOptions.RightToLeft);

var strValueWithout = regex.Replace(strValue, "$1$2$5");
var extractedPart = regex.Replace(strValue, "$4");

С примером кода: http://ideone.com/5OSs0

Еще одно обновление (становится скучно)

Regex Regex = new Regex(@"^(?<1>.*?)(?<2>[-/ ;(]*)(?<=\b)(?<3>[A-Z.]+)(?=\b)(?<4>.*?)$|^(?<1>.*)$", RegexOptions.RightToLeft);
Regex Regex2 = new Regex(@"^(?<1>.*?)(?<2>[-/ ;(]*)(?<=\b)(?<3>(?:\p{Lu}|\.)+)(?=\b)(?<4>.*?)$|^(?<1>.*)$", RegexOptions.RightToLeft);

var str1 = Regex.Replace(str, "$1$4");
var str2 = Regex.Replace(str, "$3");

Разница между ними заключается в том, что первый будет использовать символы A-Z в верхнем регистре, второй будет использовать другие символы "верхнего регистра", например ÀÈÉÌÒÙ

С примером кода: http://ideone.com/FqcmY

6 голосов
/ 11 марта 2011

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

Match lastSeparator = Regex.Match(strExample,
                                  @"(?<=\b\p{Lu}+)[-/ ;(](\p{Lu}+)\b",
                                  RegexOptions.RightToLeft); // last match
string main = lastSeparator.Result("$`$'");  // before and after the match
string word = lastSeparator.Groups[1].Value; // word after the separator

Это регулярное выражение немного сложнее.Основные приемы:

  • Используйте RegexOptions.RightToLeft для поиска последнего совпадения.
  • Использование Match.Result для замены.
  • $`$' в качестве строки замены: http://www.regular -expressions.info / refreplace.html
  • \p{Lu} для заглавных букв, вы можете изменить это значение на [A-Z], если вам удобнеес этим.

  • Если слово не должно следовать за заглавным словом, вы можете упростить регулярное выражение до:

    @"[-/ ;(](\p{Lu}+)\b"  
    
  • Если вам нужны и другие символы, вы можете использовать класс символов (и, возможно, удалить \b).Например:

    @"[-/ ;(]([\p{Lu}.,]+)"
    

Рабочий пример: http://ideone.com/U9AdK

4 голосов
/ 14 марта 2011

использовать список строк, установить для него все слова

найдите индекс /, затем используйте ElementAt(), чтобы определить слово для разделения, которое в вашем вопросе является "SHAM".

в вашем предложении ниже ваш индекс / будет 6.

string strSentence ="This TASK is assigned to ANIL/SHAM in our project"; 

затем используйте ElementAt(6) в конце

index - это индекс / в вашем List<string>

str = str.Select(s => strSentence.ElementAt(index+1)).ToList();

это вернет вам ШАМ

str = str.Delete(s => strSentence.ElementAt(index+1));

это удалит SHAM, а затем просто напечатает strSentence без SHAM

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

Моя идея верна, я думаю, но код может быть не таким безупречным.

3 голосов
/ 11 марта 2011

В качестве подтверждения концепции вы можете повторно реализовать Split в LINQ, используя TakeWhile и SkipWhile

    string strValue  = "this is test A/ABC";
    var s1=new string(
        strValue
        .TakeWhile(c => c!= '/')
        .ToArray());
    var s2=new string(
        strValue
        .SkipWhile(c => c!= '/')
        .Skip(1)
        .ToArray());

Я думаю, что полученный код настолько уродлив, что я надеюсь, что вы решите не использовать linq

3 голосов
/ 11 марта 2011

Вы можете использовать комбинацию метода string.Split() и класса Regex. Простой Split подходит для простых случаев, таких как разбиение по символу /. Регулярные выражения идеально подходят для сопоставления с более сложными шаблонами.

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