【问题标题】:Check if string contains a word检查字符串是否包含单词
【发布时间】:2014-01-25 11:18:45
【问题描述】:
Random rnd = new Random(DateTime.Now.Millisecond);

string rt = "tst xtstx xtste tst tst!!";

if (rnd.Next(3) == 0)
{
    string[] replaceWords = { "something", "nice" };
    rt.Replace("tst", replaceWords[rnd.Next(replaceWords.Length - 1)]);
}
if (rnd.Next(3) == 0)
{
    string[] replaceWords = { "cool", "crazy" };
    rt.Replace("xtste", replaceWords[rnd.Next(replaceWords.Length - 1)]);
}

我想用 33% 的机会从数组中随机替换一个单词。问题是如果我运行它,它将替换所有出现的 tst,并且只替换这个出现:

string rt = "tst xtstx xtste tst tst!!";
//           /\              /\  /\

有更好的方法来做到这一点,只替换单词? 我将在我的代码中多次使用相同的想法。

【问题讨论】:

  • @crush replce("\btst\b") ?
  • 我对你想要做什么有点困惑我想......你能更好地澄清你的问题吗?

标签: c# regex arrays string replace


【解决方案1】:

您需要为此使用正则表达式。

匹配所有tst单词的正则表达式,你需要使用\btst\b正则表达式。

要替换所有出现,请使用Regex.Replace 方法之一。

Here is a something similar example

同样不要使用Random(DateTime.Now.Millisecond)Random 的默认构造函数比这有更好的种子。

例子:

static Random rnd = new Random();
static string Replace(string input, string word, params string[] words)
{
     return Regex.Replace(input, "\b" + word + "\b", m=>words[rnd.Next(words.Length)]);
}

现在你可以这样使用它了:

string rt = "tst xtstx xtste tst tst!!";

if (rnd.Next(3) == 0)
{
    rt = Replace(rt, "tst", "something", "nice");
}
if (rnd.Next(3) == 0)
{
    rt = Replace(rt, "xtste", "cool", "crazy");
}

【讨论】:

  • 有一种干净的方法可以做到这一点吗?因为我要多次重复同样的想法?
  • 如果使用 Radom rnd 这 2 行,我将需要多个?
  • 为什么使用 m=>words[rnd.Next(words.Length)] 插入 words[rnd.Next(words.Length)]?
  • 当您使用words[rnd.Next(words.Length)] 时,您传递了一个选定的单词,它会用这个单词替换所有找到的单词。但是当您传递m=>words[rnd.Next(words.Length)] 时,您传递了一个函数,该函数将为找到的每个匹配项调用以选择替换,因此每个替换将是随机的。
【解决方案2】:

您可以使用\b 表示带有正则表达式的单词边界。

另外 - 不要忘记分配回原始字符串!

Random rnd = new Random();

string rt = "tst xtstx xtste tst tst!!";

if (rnd.Next(3) == 0)
{
    string[] replaceWords = { "something", "nice" };
    rt = Regex.Replace(rt, @"\btst\b", replaceWords[rnd.Next(replaceWords.Length - 1)]);
}
if (rnd.Next(3) == 0)
{
    string[] replaceWords = { "cool", "crazy" };
    rt = Regex.Replace(rt, @"\bxtste\b", replaceWords[rnd.Next(replaceWords.Length - 1)]);
}

【讨论】:

    【解决方案3】:

    这样做。使用 Regex.Replace/b 仅使用单词。

    Random rnd = new Random(DateTime.Now.Millisecond);
    
    string rt = "tst xtstx xtste tst tst!!";
    
    if (rnd.Next(3) == 0)
    {
        string[] replaceWords = { "something", "nice" };
        rt = Regex.Replace(rt, @"\tst\b", replaceWords[rnd.Next(replaceWords.Length - 1)]);
    }
    if (rnd.Next(3) == 0)
    {
        string[] replaceWords = { "cool", "crazy" };
        rt = Regex.Replace(rt, @"\xtste\b", replaceWords[rnd.Next(replaceWords.Length - 1)]);
    }
    

    做一些重复工作的方法。

    public string ReplaceRandom(string[] words, string wordToReplace, string inputString)
    {
        Random rnd = new Random(DateTime.Now.Millisecond);
        inputString = Regex.Replace(inputString, @"\b" + wordToReplace + @"\b", words[rnd.Next(words.Length - 1)]);
        return inputString;
    }
    

    或者,如果您想使用扩展方法来坚持String.Replace 的思路,您可以这样做。用rt.ReplaceWithRandom(replaceWords, "tst");调用它

    public static string ReplaceWithRandom(this string inputString, string[] words, string wordToReplace)
    {
        Random rnd = new Random(DateTime.Now.Millisecond);
        inputString = Regex.Replace(inputString, @"\b" + wordToReplace + @"\b", words[rnd.Next(words.Length - 1)]);
    }
    

    【讨论】:

    • 既然我要多次使用这段代码,有办法让它更干净吗?
    • @Gorfi 你是想把这个功能拉到一个单独的函数中还是只是让代码更短?
    • 用 replaceWords 数组轻松实现一个新的 wordToReplace。
    • @Gorfi 我加了一个函数,看看是不是你要的。
    • 为什么使用 x => words[rnd.Next(words.Length)]) 而不是 words[rnd.Next(words.Length)])
    【解决方案4】:

    在我看来,您希望每场比赛都使用不同的随机词。这是一个可以为你做这件事的课程。

    public class RandomStringReplacer
    {
        // no need to seed this w/ the current time, the default constructor does that already
        private readonly Random _random = new Random();
    
        private readonly Regex _regex;
    
        private readonly string[] _replacementStrings;
    
        public RandomStringReplacer(string pattern, params string[] replacementStrings)
        {
            _regex = new Regex(pattern);
            _replacementStrings = replacementStrings.ToArray();
        }
    
        // each time we get a replacement string, a randomly selected one is chosen
        private string RandomReplacement
        {
            get { return _replacementStrings[_random.Next(_replacementStrings.Length)]; }
        }
    
        public string Replace(string text)
        {
            var random = new Random();
            var result = text;
    
            // get the matches as a stack, because we want to replace backwards so that indexes still match the correct spot in the string
            var matches = new Stack<Match>(_regex.Matches(text).OfType<Match>());
            while (matches.Count > 0)
            {
                var match = matches.Pop();
                // each match has a 1/3 chance to be replaced
                if (random.Next(3) == 0)
                {
                    result = result.Remove(match.Index, match.Length).Insert(match.Index, RandomReplacement);
                }
            }
            return result;
        }
    }
    

    用法:

    var replacements = new[]{"foo", "bar", "FUBAR"};
    var pattern = @"(tst)|(xtste)";
    var replacer = new RandomStringReplacer(pattern, replacements);
    
    var text = "tst xtstx xtste tst tst!!";
    replacer.Replace(text).Dump();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      • 2020-06-21
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      相关资源
      最近更新 更多