# Reduce namespaces

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<IEnumerable<string>> ExplodeNamespaces(this IEnumerable<string> namespaces)
{
return namespaces.Select(Split('.'));

Func<string, IEnumerable<string>> Split(params char[] separators)
=> s => s.Split(separators);
}

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

return namespaces;

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

Func<IEnumerable<string>, IEnumerable<string>> 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

• Apparently someone doesn't like namespaces :-P – t3chb0t Apr 7 '17 at 15:32
• @Heslacher I think as long as they are pretty small it's ok but several lines might be too much indeed. I'm still experimenting so I don't know yet whether I (dis-)like them however I prefer to use a local function with a strong name rather then a magic expression, especially if it is related only to a single method. As soon as I need one in more then one place I promote it to a full member. – t3chb0t Apr 7 '17 at 16:06
• IMO they are much harder to read, especially if you are using Expression bodies on method-like members – Heslacher Apr 7 '17 at 16:09
• @Heslacher I usually try to stick to a single line and on a large monitor they don't look so weird but as soon as I need line breaks I use {}. I actually never use a formatting like in the question where the body is on a new line. I just put a line break there so that readers don't have to scroll horizontally so much. – t3chb0t Apr 7 '17 at 16:12

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<string, IEnumerable<string>> 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<string> namespaces) method that would call namespaces.ExplodeNamespaces().ReduceNamespaces() internally. It will make probably the most common use case more accessible.