9

I have string separated by dot ('.') characters that represents a hierarchy:

string source = "Class1.StructA.StructB.StructC.FieldA";

How can I use C# and linq to split the string into separate strings to show their hierarchy? Such as:

string[] result = new string[]
{
    "Class1",
    "Class1.StructA",
    "Class1.StructA.StructB",
    "Class1.StructA.StructB.FieldA"
};
Cœur
  • 37,241
  • 25
  • 195
  • 267
sean
  • 105
  • 1
  • 6

4 Answers4

12

Split the string by the delimiters taking 1...N of the different levels and rejoin the string.

const char DELIMITER = '.';
var source = "Class1.StructA.StructB.StructC.FieldA";
var hierarchy = source.Split(DELIMITER);
var result = Enumerable.Range(1, hierarchy.Length)
    .Select(i => String.Join(".", hierarchy.Take(i)))
    .ToArray();

Here's a more efficient way to do this without LINQ:

const char DELIMITER = '.';
var source = "Class1.StructA.StructB.StructC.FieldA";
var result = new List<string>();
for (int i = 0; i < source.Length; i++)
{
    if (source[i] == DELIMITER)
    {
        result.Add(source.Substring(0, i));
    }
}
result.Add(source); // assuming there is no trailing delimiter
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • Excellent answer. The linq solution is important because I'll be reading 100's of these from xml and grouping them together into auto-generated classes. – sean Jan 30 '12 at 22:09
0

Here is solution that uses aggregation:

const string separator = ".";
const string source = "Class1.StructA.StructB.StructC.FieldA";

// Get the components.
string[] components = source.Split(new [] { separator }, StringSplitOptions.None);

List<string> results = new List<string>();
// Aggregate with saving temporary results.
string lastResult = components.Aggregate((total, next) =>
    {
        results.Add(total);
        return string.Join(separator, total, next);
    });
results.Add(lastResult);
0

Here's a solution completely without LINQ:

public static string[] GetHierarchy(this string path)
{
    var res = path.Split('.');
    string last = null;
    for (int i = 0; i < res.Length; ++i)
    {
        last = string.Format("{0}{1}{2}", last, last != null ? "." : null, res[i]);
        res[i] = last;
    }
    return res;
}
Nuffin
  • 3,882
  • 18
  • 34
0

Shlemiel the painter approach is better than the "super Shlemiel" string.Join in this case.

        const char DELIMITER = '.';

        string soFar = "";
        List<string> result = source.Split(DELIMITER).Select(s =>
        {
            if (soFar != "") { soFar += DELIMITER; };
            soFar += s;
            return soFar;
        }).ToList();
Amy B
  • 108,202
  • 21
  • 135
  • 185