A Replace Method for Linq Queries

With Linq you get handy things like where, select, count etc. But there is no “replace”. It’s a relative easy job to implement a replace for IEnumerable:

from element in theList 
select object.Equals(element, searchThis) 
? replaceWithThis 
: element;

You might place this in an extension method in order to reuse that:

public static IEnumerable<TElement> Replace<TElement>(
    this IEnumerable<TElement> theList, 
    TElement searchThis, 
    TElement replaceWithThis)
{
    return from element in theList 
            select object.Equals(element, searchThis) 
            ? replaceWithThis 
            : element;
}

For a little test, I’ve set up a small output method that simply prints the elements of a list to the console:

private static void WriteElements(IEnumerable list)
{
    foreach (var element in list)
    {
        Console.Write(element);
    }

    Console.WriteLine();
}

With a small list of string elements the replacement is straight forward:

var list = new List<string> { "a", "b", "c", "d", "c" };
WriteElements(list);
WriteElements(list.Replace("c", "_"));
Console.ReadLine();

The output is:
abcdc
ab_d_

To test this with a more complex class assume this sample class:

public class ComplexClass
{
    public string Justastring { get; set; }
    public Guid Anobject { get; set; }

    public ComplexClass(string initElement)
    {
        this.Anobject = Guid.NewGuid();
        this.Justastring = initElement;
    }

    public override string ToString()
    {
        return this.Justastring //+ this.Anobject + "\n"
            ;
    }
}

The class does contain a string and a Guid. The constructor simply assigns the string and creates a new Guid, so each instance does have a unique guid.
Now execute this:

var complexList = new List<ComplexClass>
    {
        new ComplexClass("a"), 
        new ComplexClass("b"), 
        new ComplexClass("c"), 
        new ComplexClass("d"), 
        new ComplexClass("c")
    };
WriteElements(complexList);
WriteElements(complexList.Replace(new ComplexClass("c"), new ComplexClass("_")));
Console.ReadLine();

Now the output is:
abcdc
abcdc

No replacement has been made, because the instance provided as the “search for” parameter is a new instance, so it’s different to all other instances.
Executing this line will replace the 2nd element:

WriteElements(complexList.Replace(complexList[2], new ComplexClass("_")));
To have the same output as with strings, we need to override Equals, too:
public override bool Equals(object obj)
{
    var x = obj as ComplexClass;
    if (x != null)
    {
        return x.Justastring == this.Justastring;
    }
    return base.Equals(obj);
}

Remember that this might lead to other effects! You should override GetHashCode and implement other equality members in order to make the comparison consistent. But for implementing that the right way, you should think about what really means “equal” in your case.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Sylvio's Infobox

Aktuelle Themen rund um SQL Server, BI, Windows, ...

Meredith Lewis

Professional Digital Portfolio

Vittorio Bertocci

Just another WordPress.com weblog

ScottGu's Blog

Just another WordPress.com weblog

AJ's blog

Thoughts and informations I think worthwhile to share...

Outlawtrail - .NET Development

Architecture & Design

SDX eXperts Flurfunk

Just another WordPress.com weblog

%d bloggers like this: