Как заменить String дважды на oldValues ​​с одинаковым текстом внутри? - PullRequest
2 голосов
/ 26 апреля 2010

Я пытаюсь взять блок текста и отсканировать его на предмет определенного текста (имени) и превратить его в URL, а именно:

Блок текста:

Chairman Joe Smith has announced a new plan to decrease expenditures by outsourcing the planning of the new dining hall. Smith states the current project managers do not have excess time to commit to this new project and this will be less costly than hiring a new or contract project manager.

Теперь, что я пытаюсь сделать, это взять любые экземпляры председателя Джо Смита, или Джо Смита, или Смита, или председателя Смита, и поместить это в ссылку на его профиль / биографию. Используя любые известные мне строковые методы (замена строк, построитель строк, добавление текста до и после совпадающей строки), я столкнулся бы с проблемой при поиске Смита и других имен.

Если я попробую следующее:

String.replace("Smith", "<a href='smithbio.html'>Smith</a>")
String.replace("Chairman Joe Smith", "<a href='smithbio.html'>Chairman Joe Smith</a>")

Это было бы плохо, потому что везде, где Смит используется как часть его имени, не получалось, и только Смит был бы связующим звеном.

Но если я попробую обратное:

String.replace("Chairman Joe Smith", "<a href='smithbio.html'>Chairman Joe Smith</a>")
String.replace("Smith", "<a href='smithbio.html'>Smith</a>")

Это создаст вложенные ссылки.

Я думаю, может быть, мне следует использовать regex.Replace в сочетании с проверками подстрок? Но если это так, у меня возникают проблемы с тем, как это сделать. Как я могу сделать эти множественные замены, но сказать заменить эту строку, если она не является частью другого string.replacer, который вызывается? К вашему сведению: Делая это в VB, не думаю, что это имеет значение здесь, но на всякий случай ...

Ответы [ 3 ]

3 голосов
/ 26 апреля 2010

Вы должны использовать регулярное выражение, например: (VB, проверено)

Regex.Replace(str, "(Chairman\s+)?(Joe\s+)?Smith", _
    "<a href='smithbio.html'>$0</a>")

$0 является одним из нескольких выражений, которые могут быть включены в строку замены .

Если вы знаете имена только во время выполнения, вы должны обязательно позвонить Regex.Escape .

1 голос
/ 26 апреля 2010

Одна из вещей, которую вы можете сделать с объектами .NET regex, - заменить совпадение результатом делегата, переданного в Regex.Replace.

В делегате вы можете использовать результат сопоставления (и любую окружающую строку, какую пожелаете) при определении замещающего текста (возвращаемого делегатом).

0 голосов
/ 26 апреля 2010

Я не предполагаю, что вы делаете это, однако крайне важно, чтобы программисты могли выводить и рассуждать с помощью алгоритмов из проблем, с которыми они сталкиваются, особенно при поддержке устаревших баз кода. Мы испорчены всеми абстракциями высокого уровня. Мы просто спрашиваем, как я могу сделать X, Y, Z и бум, мы бросаем на него запрос RegEx или LINQ. Я не говорю, что это плохие вещи, но время от времени стоит задуматься немного глубже. Возможно, это больше предназначено для Code Golf или чего-то подобного, но если бы OP представил аргументированный алгоритм, я бы чувствовал себя намного лучше при представлении стандартного подхода, потому что тогда OP, вероятно, признал бы самостоятельно, что регулярное выражение может работать как решение.

Без использования регулярного выражения вы можете записывать и вести список индексов и длин найденных строк:

  1. Председатель Джо Смит
  2. Джо Смит
  3. Smith
  4. Председатель Смит

Затем вы пройдете по этому списку, заменив каждый элемент соответствующей ссылкой.

Я уверен, что этот алгоритм можно улучшить.

Вот пример:

class Instance
{
    public int start;
    public int length;
    public string text;
    public Instance(int _start, int _length, string _text)
    {
        start = _start;
        length = _length;
        text = _text;
    }
};

static void Main(string[] args)
{
    string test = "Chairman Joe Smith has announced a new plan to decrease expenditures by outsourcing the planning of the new dining hall. Smith states the current project managers do not have excess time to commit to this new project and this will be less costly than hiring a new or contract project manager.";
    string[] lookup = { "Chairman Joe Smith", "Joe Smith", "Smith", "Chairman Smith" };
    List<Instance> li = new List<Instance>();

    // record each instance of specified strings
    foreach (string name in lookup)
    {
        int index = 0;
        do
        {
            index = test.IndexOf(name, index);
            if (index > -1)
            {
                li.Add(new Instance(index, name.Length, name));
                index += name.Length;
            }
        } while (index > -1);
    }

    // eliminate duplicate instances
    Retry:
    foreach (Instance i in li)
    {
        foreach (Instance j in li)
        {
            if (j != i)
            {
                if ((j.start >= i.start) && (j.start + j.length <= i.start + i.length))
                {
                    li.Remove(j);
                    goto Retry;
                }
            }
        }
    }

    // replace each instance with respective text
    foreach (Instance i in li)
    {
        test = test.Remove(i.start, i.length);
        string final = "<a href='smithbio.html'>" + i.text + "</a>";
        test = test.Insert(i.start, final);
        foreach (Instance j in li)
        {
            j.start += (final.Length - i.length);
        }
    }

    Console.WriteLine(test);
    Console.ReadLine();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...