Поиск всех совпадений в строке - PullRequest
1 голос
/ 07 апреля 2020

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

using System;
using System.Linq;      
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var stringToCheck = "fooX, fooY);";

        List<string> allStrings = new List<string>{
         "fooX",
         "foo",
         "fooY"
        };

        var matches =  allStrings.Where(cmd => stringToCheck.IndexOf(cmd) > -1).ToList();

        //expected output is 2
        Console.Write(matches.Count);
    }  
}

В настоящее время я получаю все 3 строки соответствия, мой вопрос, как соответствовать 2 точных совпадения

Для контекста значение проверяемой строки является строковым представлением файла класса.

Ответы [ 4 ]

1 голос
/ 07 апреля 2020

Кажется, вы ищете целое слово соответствие; то есть "foo" не соответствует "fooX, fooY);", поскольку у нас есть fooX и fooY целых слов * только 1010 *.

если это ваш случай, вы можете используйте регулярные выражения :

using System.Text.RegularExpressions;

...

var matches = allStrings
  .Where(cmd => Regex.IsMatch(stringToCheck, $@"\b{Regex.Escape(cmd)}\b"))
  .ToList();

Редактировать: Если allStrings и stringToCheck длинные и все элементы allStrings гарантированно состоят из Только буквы ..z, вы можете попробовать более быстрое решение - разбить stringToCheck на words:

HashSet<string> words = new HashSet<string>(Regex.Split(stringToCheck, @"\W"));

, а затем проверить эти предварительно вычисленные значения words:

var matches = allStrings
  .Where(cmd => words.Contains(cmd))
  .ToList();
0 голосов
/ 07 апреля 2020

Вы можете использовать Regex и скомпилировать это выражение для повышения производительности.

      var stringToCheck = "fooX, fooY);";
        List<string> allStrings = new List<string>{
            "fooX",
            "foo",
            "fooY"
        };
        var matches = Regex.Matches(stringToCheck, $@"\b({string.Join('|', allStrings)})\b", RegexOptions.Compiled);
    }
0 голосов
/ 07 апреля 2020

Вы можете использовать регулярное выражение с метасимволом \ b для границы слова. Он будет соответствовать словам, а не подстрокам.

var stringToCheck = "fooX, fooY);";
var allStrings = new List<string> { "fooX", "foo", "fooY" };
var matches = Regex.Matches(stringToCheck, $@"\b({string.Join("|", allStrings)})\b")
                .Cast<Match>()
                .Select(x => x.Value); //And .Distinct() for unique values.
0 голосов
/ 07 апреля 2020

Вместо этого вы можете использовать метод Intersect:

var matches = stringToCheck.Split(',').Intersect(allStrings).ToList();

Но так как в вашей строке есть какой-то символ );, вам нужно сделать что-то вроде этого:

var matches = string.Join("", stringToCheck.TakeWhile(c => c != ')'))
    .Replace(" ","").Split(',').Intersect(allStrings).ToList();

https://dotnetfiddle.net/KhnKyT

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