4

Is it possible to write a lambda expression that will iterate through array of objects and replace all occurences of 'X', 'Y', ' ' and 'Z' in one of the properties?

E.g.

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

For some reason, a query above doesn't replace a single character, when I need to replace multiple characters.

Thank you

5 Answers 5

8

When I want to replace one of a number of characters with one single other character, I often use a combination of string.Split and string.Join:

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

This will replace any occurrence of 'X', 'Y' or 'Z' with '_'. You can combine this with the looping construct of your choice.

As discussed in the comments, using Select does not really add any value in this case. A normal foreach loop would do the job, and would even produce more compact code:

char[] unwanted = new[] {'X', 'Y', 'Z'};
foreach(var x in query)
{
    x.SomePropertyName = string.Join("_", x.SomePropertyName.Split(unwanted));
};
Sign up to request clarification or add additional context in comments.

7 Comments

It's a bit of an abuse of the Select method though!
Does this work if the first or final character is 'X', 'Y', or 'Z'? Eg. Does 'XBC' return 'BC' and 'ABX' return 'AB'? Or does 'XYZ' return '___'?
@LukeH: I absolutely agree :) I would personally probably just use a foreach loop.
@Robert: yes, it works also when the unwanted characters appears first or last in the string.
It's interesting that you say it's an "abuse of the Select method". I thought that LINQ solution would be more elegant, but that was just my assumption. What is the reasoning behind your statement?
|
6

If you want to use LINQ, you can use Select, ToArray and the String(char[]) constructor like this:

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

Note that LINQ is not intended to be used to cause side-effects, but to create new enumerables from existing enumerables. So a foreach loop is better here.


But why not simply a chain of Replace calls?

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

Or are you trying to replace a single character with a sequence of characters? Then use the String.Replace overload that takes two strings:

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

Comments

2

If you're in the mood to use a regular expressions, you can do something like this:

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

Comments

1

Although you requested LINQ, this (ab)use of LINQ relies on side-effects and clutters the code. An alternative to use with an array of objects (which you stated is the case in your question) is to use the 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));

Of course use of regex requires some knowledge. Be mindful of using metacharacters that hold a special meaning in regex. You can sanitize your characters by using the Regex.Escape method.

1 Comment

Man... this is even less legible than the LINQ... (I mean the regex approach)
0

loop through each character in the string and replace it if necessary.

 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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.