【问题标题】:Remove all characters after the last letter删除最后一个字母之后的所有字符
【发布时间】:2013-04-23 03:33:47
【问题描述】:

以下简单程序将查找用户输入的字符串中的最后一个字母,然后删除该点之后的所有内容。因此,如果一个人输入一个string....,则应该删除g 之后的所有内容。我有以下作为一个小程序:

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Enter in the value of the string: ");
        List<char> charList = Console.ReadLine().Trim().ToList();

        int x = charList.LastIndexOf(charList.Last(char.IsLetter)) ;
        Console.WriteLine("this is the last letter {0}", x);
        Console.WriteLine("This is the length of the string {0}", charList.Count);
        Console.WriteLine("We should have the last {0} characters removed", charList.Count - x);

        for (int i = x; i < charList.Count; i++)
        {
            charList.Remove(charList[i]);
        }

        foreach (char c in charList)
        {
            Console.Write(c);
        }
        Console.ReadLine();
    }
}

我已经尝试了很多变体,但没有一个能准确地写出来。这个特定程序的输入为string....,程序的输出为strin..,所以它以某种方式离开了它应该带走的东西,实际上它带走了它不应该带走的字母。任何人都可以说明为什么会这样吗?所需的输出应该是string

【问题讨论】:

  • 为什么不直接使用input.Substring(0, x + 1)
  • @Grant Thomas:因为如果 x 不存在并且所有元素都被删除,x 可能是 -1,也许这就是意图,从“规范”中并不清楚。
  • @MichelKeijzers 这无关紧要。关键是所有的循环都是一场闹剧——值的验证是微不足道的。

标签: c# visual-studio-2010


【解决方案1】:

试试这个:

string input = Console.ReadLine();                // ABC.ABC.
int index = input.Select((c, i) => new { c, i })
                 .Where(x => char.IsLetter(x.c))
                 .Max(x => x.i);
string trimmedInput = input.Substring(0, index + 1);
Console.WriteLine(trimmedInput);                  // ABC.ABC

【讨论】:

  • +1 不需要substringString.Join("", input.TakeWhile(char.IsLetter))
  • 这会失败!这不会查找最后一个字母,它会查找第一个非字母并删除其余的,包括它后面的字母。
  • 是的,这在"ABC.ABC." 上失败了(根据规范)应该产生"ABC.ABC"
  • @MartinMulder / MatthewWatson 不如我最初的解决方案优雅,但它更好地满足要求。
【解决方案2】:

请解释一下,这是因为每次删除一个字符时,都会增加 i 计数器,但也会减少 charList.Count,因此实际上删除了 1 个字符,留下下一个字符,然后再次删除,依此类推.. .

例如,输入 "string...." 和 x 为 5(G 字母的索引),你正在做:

第一次迭代: 删除 g 字符,使 x 变为 6,charList.Count 变为 9 (10-1)

下一次迭代: 删除索引 6 处的字符,现在是第二个。 (你的字符串是“strin....”)。

所以你错过了第一点。

我让您检查其他答案,因为它们包含针对您的问题的更优雅的解决方案。

【讨论】:

  • 这就是我要找的。感谢您的洞察力,我相信这会对我有所帮助。
【解决方案3】:

我认为将Substring 用户输入的string 简单得多。所以考虑以下修改后的代码:

 class Program
 {
    static void Main(string[] args)
    {
        Console.Write("Enter in the value of the string: ");
        var s = Console.ReadLine().Trim();
        List<char> charList = s.ToList();

        int x = charList.LastIndexOf(charList.Last(char.IsLetter)) ;
        Console.WriteLine("this is the last letter {0}", x);
        Console.WriteLine("This is the length of the string {0}", charList.Count);
        Console.WriteLine("We should have the last {0} characters removed", charList.Count - x);

        Console.WriteLine(s.Substring(0, x + 1);
        Console.ReadLine();
    }
}

这里我们存储用户输入到s的值,找到一个字母的最后一个索引,然后在写出到控制台时通过那个字母Substring

【讨论】:

  • 我不得不说比我的问题更优雅的解决方案。 +1
  • 这将导致搜索字符数组两次。
【解决方案4】:
string s = console.ReadLine();
s = s.Substring(0, s.ToList().FindLastIndex(char.IsLetter) + 1);

【讨论】:

    【解决方案5】:

    你也可以使用一个叫做 SubString 的字符串函数,来获取从第一个字母到最后一个字母的索引。

    【讨论】:

    • 您知道程序现在的行为方式吗?
    • 删除时你这样做: for (int i = x; i
    【解决方案6】:

    这是一种非常低效的方法(只是为了好玩!)

    var trimmedInput = string.Join("", input.Reverse().SkipWhile(x => !char.IsLetter(x)).Reverse());
    

    【讨论】:

    • 如果效率这么低,为什么要发布?
    • @MartinMulder “只是为了好玩”。可能这不是你的菜!但它确实展示了 Linq 用于反转序列的一些用途,这可能会引起人们的兴趣。
    【解决方案7】:

    你可以使用这个扩展:

    public static string TrimLettersLeft(this string input)
    { 
        int lastLetterIndex = -1;
        for (int i = input.Length - 1; i >= 0; i--)
        {
            if (Char.IsLetter(input[i]))
            {
                lastLetterIndex = i;
                break;
            }
        }
    
        if( lastLetterIndex == -1)
            return input;
        else
            return input.Substring(0, lastLetterIndex + 1);
    }
    

    输入:test...abc... 输出:test...abc

    DEMO

    【讨论】:

      【解决方案8】:

      解决办法是这样的。

      string charList = "string..."; //any string place here
      int x = charList.LastIndexOf(charList.Last(char.IsLetter));
      String str = charList.ToString().Substring(0, x + 1);
      

      【讨论】:

        【解决方案9】:

        这将匹配每个单词字符(A-Z、0-9 和 _):

        string Input = Console.ReadLine();
        string Userinput = String.Empty;
        Regex TextSearch = new Regex(@"\w*");
        
        if(TextSearch.IsMatch(Input))
            Userinput = TextSearch.Match(Input).Groups[0].Value;
        else
            // No valid Input
        

        【讨论】:

        【解决方案10】:

        我认为是最短、最简单的选择:

        编辑: 评论指出了这里的初始错误,所以我添加了一些修复。现在应该可以很好地工作(可能不是最佳解决方案,但我认为这是一个有趣的简单解决方案):

        var userInput = Console.ReadLine();
        
        Console.WriteLine(new string(userInput.Reverse()
                                              .SkipWhile(c => !char.IsLetter(c))
                                              .Reverse()
                                              .ToArray()));
        

        【讨论】:

        • 这会失败!这不会查找最后一个字母,它会查找第一个非字母并删除其余的,包括它后面的字母。
        • @MartinMulder 感谢您指出这一点,您说的很对。现在做了一点改动,所以我相信现在应该是正确的。
        • 很好......但是......请注意:这个答案已经由 Matthew Watson 提出。
        • 巧合,那又怎样?我最初的答案是在这里,并稍作改动。大不了。 (此外,我的可以说是更具可读性,无论是最初还是编辑后;))
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-05
        • 1970-01-01
        • 2023-01-30
        • 1970-01-01
        • 1970-01-01
        • 2020-03-12
        • 2014-11-08
        相关资源
        最近更新 更多