MartinHansen
MartinHansen

Reputation: 21

Splitting and grouping strings

I'm using ASP.NET Webforms, and have several C# strings representing parent and child categories. The strings are on this form:

parent>child

And i would like to split the string and list each child under the correct parent. My end goal is to be able to output these parent and child categories on my webpage like this:

<li>Parent
  <ul>Child 1</ul>
  <ul>Child 2</ul>
</li>

For example, if I have the following strings:

string cat1 = "fish>shark";
string cat2 = "fish>nemo";
string cat3 = "birds>eagle";
string cat4 = "birds>hawk";

I want to display them on my page like this:

  • Fish
      Shark
      Nemo
  • Birds
      Eagle
      Hawk
  • What would be the best approach to accomplish this?

    Upvotes: 1

    Views: 377

    Answers (2)

    canon
    canon

    Reputation: 41665

    I'm not sure whether you simply want to create the markup as a string or if you'd like to do things with the list and its children as ASP.NET controls. At any rate, here's an option:

    HtmlGenericControl rootUl, parentLi, childLi;
    
    // create the html list
    rootUl = new HtmlGenericControl("ul");
    
    // our name-control mapping
    var controls = new Dictionary<string, HtmlGenericControl>();              
    
    // our data
    var items = new[]{
        "fish>shark>mako",
        "fish>shark>tiger",
        "fish>clown fish>nemo",
        "birds>eagle>bald eagle",
        "birds>hawk",
    };        
    
    // loop through the data items
    foreach (var item in items)
    {
        // split by the greater-than symbol
        var names = item.Split('>');
    
        // if we don't already have a control for the topmost parent...
        if (!controls.TryGetValue(names[0], out parentLi))
        {
            // create the control and store it in our mapping
            controls[names[0]] = parentLi = new HtmlGenericControl("li")
            {
                InnerText = names[0]
            };               
            // add it to the html list
            rootUl.Controls.Add(parentLi);
        }
    
        // loop through the remaining parts
        foreach (var name in names.Skip(1))
        {
            // if the parent doesn't have a list-child...
            if (parentLi.Controls.Count == 1)
            {
                // add an html list child to the parent
                parentLi.Controls.Add(new HtmlGenericControl("ul"));
            }
    
            // if we don't already have a control for the child...
            if (!controls.TryGetValue(name, out childLi))
            {
                // create the control
                controls[name] = childLi = new HtmlGenericControl("li"){
                    InnerText = name
                };
            }
    
            // add the child to the parent's html list
            parentLi.Controls[1].Controls.Add(childLi);
    
            // keep a reference to the child for further nesting
            parentLi = childLi;
        }
    }
    
    // add the html list to the form
    form1.Controls.Add(rootUl);
    

    This results in the following output:

    <ul>
      <li>fish
        <ul>
          <li>shark
            <ul>
              <li>mako</li>
            </ul>
          </li>
          <li>nemo</li>
        </ul>
      </li>
      <li>birds
        <ul>
          <li>eagle
            <ul>
              <li>bald eagle</li>
            </ul>
          </li>
          <li>hawk</li>
        </ul>
      </li>
    </ul>

    Upvotes: 2

    mageos
    mageos

    Reputation: 1291

    I would create a hash table of lists:

     Dictionary<string, List<string>> data;
    

    and then I would loop through all the strings and put them in the structure:

     foreach (var pair in stringList)
     {
          string[] split = pair.split('>');
          if (data.ContainsKey(split[0]) == false)
              data.Add(split[0], new List<string>());
    
          data[split[0]].Add(split[1]);
     }
    

    Something like that should work. I haven't compiled it so you may have to make some tweaks, but it should give you the basic idea.

    To output the data:

     foreach (string parent in data.Keys)
     {
          // Output parent data
    
          foreach (string child in data[parent])
          {
               // Output each child.
          }
     }
    

    Upvotes: 3

    Related Questions