【问题标题】:How do I remove all nonalphabetic characters from a string? [duplicate]如何从字符串中删除所有非字母字符? [复制]
【发布时间】:2018-12-02 11:15:58
【问题描述】:

我必须编写一个程序来检查输入是否是回文,并且在这段代码中,我需要有一个从字符串中删除所有非字母字符的方法。做这个的最好方式是什么?将输入转换为数组是否更好(现在我将其作为字符串进行)?我不想为每个单独的字符编写一个循环或将每个字符都放入修剪中。修剪也会去掉中间的东西吗?

我也不允许使用正则表达式、可枚举或抛出新异常,因为教授不喜欢后两者,第一个不起作用,它只会抛出错误。

我这样做的方式似乎不是解决这个问题的最有效方式。

我的代码在这里:

 public partial class frmPalindrome : Form
{
    public frmPalindrome()
    {
        InitializeComponent();
    }

    //allows btnCheck to take in user input in txtEnterWordPhrase and check if it is a palindrome
    private void btnCheck_Click(object sender, EventArgs e)
    {
        try
        {
            if (IsValidData())
            {
                string strPhrase = Convert.ToString(txtEnterWordPhrase.Text);
                string strCleanPhrase = CharacterStrip(strPhrase);

                txtPalindrome.Text = Convert.ToString(IsPalindrome(strCleanPhrase));
            }
        }
        catch (Exception ex) //catches any other exceptions
        {
            MessageBox.Show(ex.Message + "\n\n" + ex.GetType().ToString() + "\n" + ex.StackTrace, "Exception");
        }
    }

    //a method that cuts all the nonalphabetic characters out of txtEnterWordPhrase
    public string CharacterStrip(string Phrase)
    {
        //neither of these seem very efficient
        //Phrase = Phrase.Trim(new Char[] {' ', '&', '*', ',', '-', '_', '/', '\', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',  });

        while (Phrase.IndexOf(" ") >= 0)
        {
           int intIndex = Phrase.IndexOf(" ");
           Phrase.Remove(intIndex, 1);
        }

        return Phrase;
    }

    //checks if the input is a palindrome
    public bool IsPalindrome(string Phrase)
    {
        //not sure how to do this yet
        return true; //have not built this method yet
    }

    //checks that the input is valid
    public bool IsValidData ()
    {
        return IsString(txtEnterWordPhrase, "Enter a Word or Phrase"); //have not built this validation method yet
    }

    //checks that the input in txtEnterWordPhrase is a string
    public bool IsString(TextBox Textbox, string Name)
    {
        decimal Number = 0m;

        if (Decimal.TryParse(Textbox.Text, out Number))
        {
            MessageBox.Show(Name + " must be a word or phrase.", "Entry Error");
            return false;
        }
        else
            return true;

    }

    //allows btnExit to close the program
    private void btnExit_Click(object sender, EventArgs e)
    {
        this.Close();
    }

    //a method that clears txtPalindrome and returns focus to txtEnterWordPhrase
    private void ClearResults(object sender, EventArgs e)
    {
        txtPalindrome.Text = "";
        txtEnterWordPhrase.Focus();
    }
}

【问题讨论】:

  • 为什么您认为使用 .Trim 效率如此之低?我会说它的工作效率很高,但它并没有达到我认为您期望的效果;它只会从字符串的开头和结尾删除这些字符。
  • @andresairr 我没有意识到它只是开始和结束,我正在寻找在整个字符串中都有效的东西。如果用户输入“test 12 test”我需要把它变成“testtest”
  • Code Review(提问前记得阅读帮助)
  • @user202729 你只是想给我看另一个网站吗?

标签: c#


【解决方案1】:

一个简单的 LINQ 解决方案类似于

    string exampleString = "123 Example Text 456"; 
    string onlyAlpha = new string(exampleString.Where(c => Char.IsLetter(c)).ToArray());
    Console.WriteLine(onlyAlpha);

输出:

Example Text

实际上没有任何方法可以避免在某种程度上循环遍历字符串。

【讨论】:

  • 这会删除文本中间的任何数字吗?
  • 是的。它本质上是遍历整个字符串,并且只保留在传递给 Char.IsLetter() 时返回 true 的字符。
【解决方案2】:

首先,您的示例方法CharacterStrip 存在一些问题。 Phrase.Trim() 只会修剪字符串开头和结尾的字符,因此一旦遇到不在数组中的字符,它将假定它属于,并停止处理。因此,它不会从您的字符串中删除所有非字母字符。

其次,Phrase.Remove() 返回一个删除了该 1 个字符的新字符串 - 您没有使用它。您可能打算再次将结果分配给Phrase。 C# 中要学习的一个重要原则是字符串的不变性:一旦有了字符串,就不能更改它,只能从中创建一个新字符串,在这种情况下,它具有给定索引中的字符删除。也就是说,即使有了这个修改,您的 while 循环也不会删除非字母字符,它只会删除空格。

所以,在担心效率之前,让我们先从一些可行但不优雅的东西开始:

public string CharacterStrip(string phrase)
{
    string[] chars = new string[] { " ", "&", "*", ",", "-", "_", "/", "\\", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", };

    foreach (string c in chars)
        phrase = phrase.Replace(c, "");

    return phrase;
}

这有一个缺点,您需要维护您的字符数组(存储为字符串)以包含所有非字母字符,目前还没有,但这是一个开始。

按照马特的回答建议,使用Char.IsLetter 的另一种方法是在原始字符串上使用循环。这意味着您不需要维护要删除的字符数组。

string output = "";
foreach (char c in phrase)
{
    if (Char.IsLetter(c))
        output = output + c;
}

return output;

但是,这仍然会为每个循环迭代一遍又一遍地创建新的字符串(请记住,字符串就是这样工作的),这不是很有效。 最有效的是,您可以使用奇妙的StringBuilder 类,它维护一个可变 字符/字符串集合,以便在您完成后组装成一个字符串。如果您有兴趣以有效的方式进行大量字符串操作,值得一读:

StringBuilder builder = new StringBuilder();

foreach (char c in phrase)
{
    if (Char.IsLetter(c))
        builder.Append(c);
}

return builder.ToString();

【讨论】:

  • 请反对者花时间解释原因吗?
  • 我不允许使用 StringBuilder,因为我的教授不是粉丝,但你的中间例子效果很好
  • 有趣。你的教授到底不喜欢StringBuilder 的什么地方?
  • 老实说,我不确定,这是一个夏季学期,所以她浏览了教科书,当我们读到这个时,她说“不要使用这个,我不喜欢它”并继续前进
【解决方案3】:

就这么简单:

Regex rgx = new Regex("[^a-zA-Z0-9 -]");
phrase= rgx.Replace(phrase, "");

【讨论】:

  • .NET 字符串没有方法 replaceAll。那将是 Java。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 2013-04-30
  • 2013-01-19
  • 1970-01-01
  • 2015-02-26
  • 2011-05-22
  • 2015-11-14
相关资源
最近更新 更多