使用C#从字符串中删除数组中的单词

6
我需要根据一组单词从字符串中删除单词:
我想要删除的单词:
DE DA DAS DO DOS AN NAS NO NOS EM E A AS O OS AO AOS P LDA AND

如果我收到这样的字符串:

编辑: 这个字符串已经被清理了,没有任何符号

THIS IS AN AMAZING WEBSITE AND LAYOUT

结果应该是:
THIS IS AMAZING WEBSITE LAYOUT

到目前为止,我已经:
public static string StringWordsRemove(string stringToClean, string wordsToRemove)
{
    string[] splitWords = wordsToRemove.Split(new Char[] { ' ' });

    string pattern = "";

    foreach (string word in splitWords)
    {
        pattern = @"\b" + word + "\b";
        stringToClean = Regex.Replace(stringToClean, pattern, "");
    }

    return stringToClean;
}

但是它没有删除这些单词,有什么想法吗?
我不知道我是否使用了最有效的方法来完成它,也许把这些单词放在一个数组中只是为了避免一直分割它们?
谢谢。

你的代码输出什么? - Shaharyar
10
我对C#的了解不是很深,但第二个"\b"前面应该加一个@符号吗? - Sean Bright
2
如果句子以 A 开头怎么办? - zimdanen
对于那些仅支持此示例的解决方案的回答者,您可以只需执行return "THIS IS AMAZING WEBSITE LAYOUT"; - Jodrell
@Jodrell,但你总是有一些特殊的前提条件,比如没有特殊字符。 - Viktor Mellgren
7个回答

9
private static List<string> wordsToRemove =
    "DE DA DAS DO DOS AN NAS NO NOS EM E A AS O OS AO AOS P LDA AND".Split(' ').ToList();

public static string StringWordsRemove(string stringToClean)
{
    return string.Join(" ", stringToClean.Split(' ').Except(wordsToRemove));
}

修改以处理标点符号:

public static string StringWordsRemove(string stringToClean)
{
    // Define how to tokenize the input string, i.e. space only or punctuations also
    return string.Join(" ", stringToClean
        .Split(new[] { ' ', ',', '.', '?', '!' }, StringSplitOptions.RemoveEmptyEntries)
        .Except(wordsToRemove));
}

但是,如果 stringToClean 中有标点符号呢? - Jodrell
嗨,感谢您的帮助。我选择了您的答案,因为它是更快的解决方案,且没有迭代。问候。 - Patrick
所有标点符号如 ", £, $, %, ^, &, (, ), -, _, +, =, [, ], {, }, :, ;, @, #, ~ 等等,怎么处理呢? - Jodrell
@Jodrell,如果你只有非常有限的一组数据,你可以将它们全部插入到修改后版本的Split()调用中,尽管OP说他已经从输入中删除了它们。为了讨论的方便,我建议分两步解决问题:1)预处理字符串以删除任何标点符号,2)对其进行标记化并删除不需要的单词。对于1),您可以在这里查看答案。 - Fung
@Patrick,我在我的系统上进行了性能测试,使用您的测试数据,这个Linq方法比我回答中的Regex方法快约4倍。我给你点赞。如果有人感兴趣,测试代码可用。我怀疑随着stringToClean的增长可能会有一些变化,但这不是问题的关键。 - Jodrell
我必须在调用的末尾添加.ToArray()才能使其工作。返回string.Join(" ", stringToClean.Split(' ').Except(wordsToRemove).ToArray()); - wirble

1
我刚刚修改了这一行。
pattern = @"\b" + word + "\b";

到这里

pattern = @"\b" + word + @"\b"; //added '@' 

我得到了结果

这是一个惊人的网站布局

如果你使用String.Empty而不是""会更好,例如:

stringToClean = Regex.Replace(stringToClean, pattern, String.Empty);

我同意你的观点,但是你可以通过创建一个统一的表达式来减少迭代。https://dev59.com/53TYa4cB1Zd3GeqPvoSc#17679108 - Jodrell
嗨,感谢您的帮助。我选择了@Fung的答案,因为它更快且没有迭代。问候。 - Patrick
@Patrick Fung的答案在评估Except时执行迭代。 - Jodrell
@Jodrell,抱歉我不知道。 - Patrick

1

我使用了LINQ

string exceptions = "DE DA DAS DO DOS AN NAS NO NOS EM E A AS O OS AO AOS P LDA AND";
string[] exceptionsList = exceptions.Split(' ');

string test  ="THIS IS AN AMAZING WEBSITE AND LAYOUT";
string[] wordList = test.Split(' ');

string final = null;
var result = wordList.Except(exceptionsList).ToArray();
final = String.Join(" ",result);

Console.WriteLine(final);

1
做得很漂亮!就像函数式编程应该的那样明确和准确! - Viktor Mellgren
然而,如果stringToClean包含不是空格的单词边界,比如`',','。','?','"'等等,那么你就会陷入困境。请注意,这组单词边界很大且不断增长。 - Jodrell
更多的反馈是:只需执行return String.Join(" ",result); - Viktor Mellgren
嗨,感谢您的帮助。我选择了@Fung的答案,因为它是更快的解决方案,且没有迭代。问候。 - Patrick

0

你会得到的输出是"这是一个惊人的网站布局"。

我遇到了一个问题,它会在结果中留下单词"D"(所以它变成了"这是一个惊人的网站D布局"),因为如果你使用replace函数,它只会替换某个部分的单词。如果检测到你定义的字符,这将删除整个单词(我想这就是你想要的?)。

        string[] tabooWords = "DE DA DAS DO DOS AN NAS NO NOS EM E A AS O OS AO AOS P LDA AND".Split(' ');
        string text = "THIS IS AN AMAZING WEBSITE AND LAYOUT";
        string result = text;

        foreach (string word in text.Split(' '))
        {
            if (tabooWords.Contains(word.ToUpper()))
            {
                int start = result.IndexOf(word);
                result = result.Remove(start, word.Length);
            }
        }

这不会剥离所有的 AEO 等字符吗? - Jodrell
嗨,谢谢你的帮助。我选择了你的答案,因为它更快,且没有迭代的解决方案,我可以在任何WordsToRemoveStrin中使用。问候。 - Patrick

0
public static string StringWordsRemove(string stringToClean, string wordsToRemove)
{
    string[] splitWords = wordsToRemove.Split(new Char[] { ' ' });
    string pattern = " (" + string.Join("|", splitWords) + ") ";
    string cleaned=Regex.Replace(stringToClean, pattern, " ");
    return cleaned;
}

喜欢我的答案但稍后。 - Jodrell
你好,感谢你的帮助。我选择了Fung的答案,因为它提供了一个更快速和功能性的解决方案。祝好。 - Patrick

0

怎么样,

// make a pattern to match all words 
var pattern = string.Format(
    @"\b({0})\b",
    string.Join("|", wordsToremove.Split(new[] { ' ' })));

// pattern will be of the form "\b(badword1|badword2|...)\b"

// remove all the bad words from the string in one go.    
var cleanString = Regex.Replace(stringToClean, pattern, string.Empty);

// normalise the white space in the string (one space at a time)
var normalisedString = Regex.Replace(cleanString, @"\s+", " ");

第一行创建了一个匹配要删除单词的模式。 第二行一次性替换所有单词,节省了不必要的迭代。 第三行规范化了字符串中的空格。

功能性很重要,但易读性也同样重要。你应该考虑你的格式。简洁并不总是更好。 - Lotok
@Jodrell 你好,谢谢!但是我仍然得到单词之间的空格。有什么想法吗?问候。 - Patrick
@Patrick,这是因为只有单词被替换了,而空格没有。就像你的例子一样。 - Jodrell
@Patrick,我已经添加了第三行代码来规范化空格。 - Jodrell
嗨,谢谢你的帮助。我选择了Fung的答案,因为它提供了更快且功能性的解决方案。问候。 - Patrick

0

或者...

stringToClean = Regex.Replace(stringToClean, @"\bDE\b|\bDA\b|\bDAS\b|\bDO\b|\bDOS\b|\bAN\b|\bNAS\b|\bNO\b|\bNOS\b|\bEM\b|\bE\b|\bA\b|\bAS\b|\bO\b|\bOS\b|\bAO\b|\bAOS\b|\bP\b|\bLDA\b|\bAND\b", String.Empty);
stringToClean = Regex.Replace(stringToClean, "  ", String.Empty);

2
嗯,为什么不键入 @"\b(DE|DA|DAS|DO|DOS|AN|NAS|NO|NOS|EM|E|A|AS|O|OS|AO|OS|P|LDA|AND)\b" - Jodrell
@Jodrell - 因为这样太简单了。:) 谢谢。 - James R.
你好,感谢你的帮助。我选择了Fung的答案,因为它更快,没有迭代的解决方案,并且我可以将其用于任何WordsToRemoveString。问候。 - Patrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接