【问题标题】:C# Stripping / converting one or more charactersC#剥离/转换一个或多个字符
【发布时间】:2009-05-11 17:53:53
【问题描述】:

有没有一种快速的方法(无需显式循环遍历字符串中的每个字符)并剥离或保留它。在 Visual FoxPro 中,有一个函数 CHRTRAN() 做得很好。它以 1:1 的字符替换,但如果在替代位置没有字符,则将其从最终字符串中剥离。例

CHRTRAN("这将是一个测试", "it", "X")

会回来

"ThXs wXll be a es"

注意原来的“i”被转换成“X”,小写的“t”被去掉了。

我查看了类似意图的替换,但没有看到任何替换的选项。

我正在寻找一些通用例程来验证具有不同类型输入限制的数据的多个来源。一些数据可能来自外部来源,因此我需要测试的不仅仅是文本框输入验证。

谢谢

【问题讨论】:

  • @Greg D - 仅当您从未使用过 FoxPro 时。我相信 Oracle 的 PL/SQL 中的 TRANSLATE 也是如此。
  • 或者 Perl 的 tr///d 运算符,如果有记忆的话。

标签: c# parsing character strip


【解决方案1】:

您只需致电String.Replace()

string s = "This will be a test";
s = s.Replace("i", "X");
s = s.Replace("t", "");

注意 Replace() 返回一个新字符串。它不会改变字符串本身。

【讨论】:

    【解决方案2】:

    这是你想要的吗?

    "This will be a test".Replace("i", "X").Replace("t", String.Empty)
    

    这是CHRTRAN 函数的简单实现——如果字符串包含\0 并且相当混乱,它就不起作用。您可以使用循环编写一个更好的,但我只是想尝试使用 LINQ。

    public static String ChrTran(String input, String source, String destination)
    {
        return source.Aggregate(
            input,
            (current, symbol) => current.Replace(
                symbol,
                destination.ElementAtOrDefault(source.IndexOf(symbol))),
            preResult => preResult.Replace("\0", String.Empty));
    }
    

    你可以使用它。

    // Returns "ThXs wXll be a es"
    String output = ChrTran("This will be a test", "it", "X");
    

    只是为了有一个干净的解决方案 - 没有 LINQ 和 \0 情况下也一样,并且由于使用了 StringBuilder,它几乎就位,但不会修改输入,当然。

    public static String ChrTran(String input, String source, String destination)
    {
        StringBuilder result = new StringBuilder(input);
    
        Int32 minLength = Math.Min(source.Length, destination.Length);
    
        for (Int32 i = 0; i < minLength; i++)
        {
            result.Replace(source[i], destination[i]);
        }
    
        for (Int32 i = minLength; i < searchPattern.Length; i++)
        {
            result.Replace(source[i].ToString(), String.Empty);
        }
    
        return result.ToString();
    }
    

    空引用处理缺失。

    受到 tvanfosson 解决方案的启发,我再次尝试了 LINQ。

    public static String ChrTran(String input, String source, String destination)
    {
        return new String(input.
            Where(symbol =>
                !source.Contains(symbol) ||
                source.IndexOf(symbol) < destination.Length).
            Select(symbol =>
                source.Contains(symbol)
                    ? destination[source.IndexOf(symbol)]
                    : symbol).
            ToArray());
    }
    

    【讨论】:

    • 不知道为什么替换最初对我不起作用,但 String.Empty 起作用了......虽然我不喜欢 Linq,但你在上下文中拥有的是类似的循环机制我会知道没有直接的等价物......我正在路上......谢谢
    【解决方案3】:

    这是我的最终功能,可以按预期完美运行。

    public static String ChrTran(String ToBeCleaned, 
                                 String ChangeThese, 
                                 String IntoThese)
    {
       String CurRepl = String.Empty;
       for (int lnI = 0; lnI < ChangeThese.Length; lnI++)
       {
          if (lnI < IntoThese.Length)
             CurRepl = IntoThese.Substring(lnI, 1);
          else
             CurRepl = String.Empty;
    
          ToBeCleaned = ToBeCleaned.Replace(ChangeThese.Substring(lnI, 1), CurRepl);
       }
       return ToBeCleaned;
    }
    

    【讨论】:

    • 我知道这是一个非常古老的线程,但是这个函数并没有按预期工作。仅当 ChangeThese/IntoThese 不包含相同字符时才有效。这是因为 String.Replace 函数会在某些条件下多次替换某些字符。如果你使用 ChrTran("Alfabet", "ABab12", "21baBA"),你会期望输出是 "2lfbaet"。然而,实际输出是“Alfaaet”。 “A”将被“2”替换,但稍后“2”将再次被“A”替换。您需要遍历输入字符串并用 char 替换 char 以防止双重替换。
    • @RiptoR,你似乎有一个好点,但不是以最初预期的方式工作。在预期的用法中,我不会在两个字符串中使用相同的字母,但适当地注明了。
    • 我很抱歉。我在寻找 Python 的 translate/maketrans 函数的 .NET 等效项时遇到了这个问题,所以我在思考这些函数是如何工作的。
    【解决方案4】:

    在这种情况下,我认为使用 LINQ 会使事情变得过于复杂。这很简单,也很重要:

    private static string Translate(string input, string from, string to)
    {
        StringBuilder sb = new StringBuilder();
        foreach (char ch in input)
        {
            int i = from.IndexOf(ch);
            if (from.IndexOf(ch) < 0)
            {
                sb.Append(ch);
            }
            else
            {
                if (i >= 0 && i < to.Length)
                {
                    sb.Append(to[i]);
                }
            }
        }
        return sb.ToString();
    }
    

    【讨论】:

      【解决方案5】:

      要“替换为空”,只需替换为空字符串即可。这会给你:

      String str = "This will be a test";
      str = str.Replace("i", "X");
      str = str.Replace("t","");
      

      【讨论】:

        【解决方案6】:

        作为字符串扩展的更通用的版本。和其他的一样,由于字符串在 C# 中是不可变的,因此它不会进行适当的翻译,而是返回一个带有指定替换的新字符串。

        public static class StringExtensions
        {
            public static string Translate( this string source, string from, string to )
            {
                if (string.IsNullOrEmpty( source ) || string.IsNullOrEmpty( from ))
                {
                    return source;
                }
        
                return string.Join( "", source.ToCharArray()
                                           .Select( c => Translate( c, from, to ) )
                                           .Where( c => c != null )
                                           .ToArray() );
            }
        
            private static string Translate( char c, string from, string to )
            {
                int i = from != null ? from.IndexOf( c ) : -1;
                if (i >= 0)
                {
                    return (to != null && to.Length > i)
                              ? to[i].ToString()
                              : null;
                }
                else
                {
                    return c.ToString();
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-04
          • 1970-01-01
          • 1970-01-01
          • 2013-12-06
          相关资源
          最近更新 更多