【问题标题】:LINQ lambda expression to replace multiple characters in a string?LINQ lambda表达式替换字符串中的多个字符?
【发布时间】:2011-04-12 05:10:20
【问题描述】:

是否可以编写一个 lambda 表达式来遍历对象数组并替换其中一个属性中所有出现的“X”、“Y”、“”和“Z”?

例如

return query.Select(x => { x.SomePropertyName= x.SomePropertyName.Trim().Replace(' ', "_"); return x; }).ToList();

由于某种原因,当我需要替换多个字符时,上面的查询不会替换单个字符。

谢谢

【问题讨论】:

    标签: c# linq replace lambda


    【解决方案1】:

    如果你想使用 LINQ,你可以像这样使用 Select、ToArray 和 String(char[]) 构造函数:

    var result = query.ToList();
    foreach (var x in result)
    {
        x.SomeProperty =
            new string(x.SomeProperty
                        .Select(c => (c == 'X' || ... || c == ' ') ? '_' : c)
                        .ToArray());
    }
    

    请注意,LINQ 不是用来产生副作用的,而是用来从现有的枚举中创建新的枚举。所以foreach 循环在这里更好。


    但为什么不简单地一连串 Replace 调用呢?

    var result = query.ToList();
    foreach (var x in result)
    {
        x.SomeProperty = x.SomeProperty
                          .Replace('X', '_')
                          .Replace('Y', '_')
                          .Replace('Z', '_')
                          .Replace(' ', '_');
    }
    

    或者您想用一系列字符替换单个字符? 然后使用需要两个字符串的 String.Replace 重载:

    var result = query.ToList();
    foreach (var x in result)
    {
        x.SomeProperty = x.SomeProperty.Replace(" ", "ABC");
    }
    

    【讨论】:

      【解决方案2】:

      当我想用一个其他字符替换多个字符中的一个时,我经常使用 string.Split 和 string.Join 的组合:

      char[] unwanted = new[] {'X', 'Y', 'Z'};
      query = query.Select(x =>
      {
          x.SomePropertyName = string.Join("_", x.SomePropertyName.Split(unwanted));
          return x;
      });
      

      这会将所有出现的'X''Y''Z' 替换为'_'。您可以将其与您选择的循环结构结合使用。

      正如 cmets 中所讨论的,在这种情况下,使用 Select 并没有真正增加任何价值。一个普通的foreach 循环就可以完成这项工作,甚至会产生更紧凑的代码:

      char[] unwanted = new[] {'X', 'Y', 'Z'};
      foreach(var x in query)
      {
          x.SomePropertyName = string.Join("_", x.SomePropertyName.Split(unwanted));
      };
      

      【讨论】:

      • 这正是我所追求的。谢谢
      • 这有点滥用Select 方法!
      • 如果第一个或最后一个字符是“X”、“Y”或“Z”,这是否有效?例如。 'XBC' 是否返回 'BC' 和 'ABX' 是否返回 'AB'?还是“XYZ”返回“___”?
      • @LukeH:我绝对同意 :) 我个人可能只使用 foreach 循环。
      • @Robert:是的,当不需要的字符出现在字符串的第一个或最后一个时,它也可以工作。
      【解决方案3】:

      如果你有心情使用正则表达式,你可以这样做:

      query.Select(
          x => { 
              x.SomePropertyName = Regex.Replace(x.SomePropertyName, @"[XYZ\s]", "_"); 
              return x; })
      

      【讨论】:

        【解决方案4】:

        遍历字符串中的每个字符并在必要时替换它。

         var xyz = new HashSet<char>(new[] { 'X', 'Y', 'Z' });
         char replacement = '_';
         var results = query
          .Select(x =>
             {
              var value = x.SomePropertyName
             .Trim()
             .Select(y => xyz.Contains(y) ? replacement : y)
             .ToArray();
              x.SomePropertyName = new string(value);
              return x;
             })
          .ToList();
        

        【讨论】:

          【解决方案5】:

          尽管您请求了 LINQ,但这种(ab)使用 LINQ 依赖于副作用并且使代码混乱。与对象数组一起使用的替代方法(您在问题中所说的就是这种情况)是使用 Array.ForEach method:

          // using Fredrik Mörk's approach
          Array.ForEach(query, x =>
              x.SomePropertyName = string.Join("_", x.SomePropertyName.Split(unwanted)));
          
          // using Regex
          Array.ForEach(query, x => x.SomePropertyName =
              Regex.Replace(x.SomePropertyName, "[XYZ]", "_", RegexOptions.IgnoreCase));
          

          当然,使用正则表达式需要一些知识。请注意在正则表达式中使用具有特殊含义的元字符。您可以使用Regex.Escape method 对您的角色进行消毒。

          【讨论】:

          • 伙计...这比 LINQ 更难读...(我的意思是正则表达式方法)
          猜你喜欢
          • 1970-01-01
          • 2016-11-09
          • 2012-04-26
          • 1970-01-01
          • 1970-01-01
          • 2016-09-21
          • 1970-01-01
          • 1970-01-01
          • 2013-01-21
          相关资源
          最近更新 更多