HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Reduce namespaces

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
reducenamespacesstackoverflow

Problem

I have a collection of full type names where I need to reduce common namespaces. For this purpose I wrote two extensions. The first one explodes each namespace into pieces and the second one removes the first name for as long as all first names are equal thus reducing each namespace.

static class Namespace
{
    public static IEnumerable> ExplodeNamespaces(this IEnumerable namespaces)
    {
        return namespaces.Select(Split('.'));

        Func> Split(params char[] separators) 
            => s => s.Split(separators);
    }

    public static IEnumerable> ReduceNamespaces(this IEnumerable> namespaces)
    {
        while (IsFirstCommon(namespaces))
        {
            namespaces = namespaces.Select(SkipFirst());
        }

        return namespaces;

        bool IsFirstCommon(IEnumerable> values) 
            => values.Select(ns => ns.FirstOrDefault()).Distinct().Count() == 1;

        Func, IEnumerable> SkipFirst() 
            => values => values.Skip(1);
    }
}


Example:

var namespaces = new[]
{
    "foo.waldo.bar.baz.qux",
    "foo.waldo.bar.baz.quux",
    "foo.waldo.bar.baaz.qux",
    "foo.waldo.baar",
};

namespaces.ExplodeNamespaces().ReduceNamespaces().Dump();


Result:

bar
baz
qux

bar
baz
quux

bar
baaz
qux

baar

Solution

Those delegates inside methods are cool and everything, but I think you are overusing them a bit. For example, compare this:

return namespaces.Select(Split('.'));

    Func> Split(params char[] separators) 
        => s => s.Split(separators);


to this:

return namespaces.Select(s => s.Split(new []{'.'}));


The second version is definitely way shorter and in my opinion is just as good (if not better), in terms of readability.

The algorithm looks alright to me. You might want to replace .Count() == 1 with, say, !....Skip(1).Any() to return earlier, but I don't think it matters for relatively small input.

It would be nice to also have a ReduceNamespaces(this IEnumerable namespaces) method that would call namespaces.ExplodeNamespaces().ReduceNamespaces() internally. It will make probably the most common use case more accessible.

Code Snippets

return namespaces.Select(Split('.'));

    Func<string, IEnumerable<string>> Split(params char[] separators) 
        => s => s.Split(separators);
return namespaces.Select(s => s.Split(new []{'.'}));

Context

StackExchange Code Review Q#160104, answer score: 2

Revisions (0)

No revisions yet.