C# string manipulation - How to remove the first element of each concatenated string in a collection

StackOverflow https://stackoverflow.com/questions/620546

  •  05-07-2019
  •  | 
  •  

Question

I am creating concatenated strings based on the data in each row of my ListView control. I need to figure out how to remove the first element in each string which pertains to a single row of the ListView. How might I accomplish this? This is a C# winforms project.

Here is my current code:

        foreach (ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
        {
            string HazPackErrRow = " ";

            foreach (ListViewItem.ListViewSubItem HazPackErrSub in HazPackErrItems.SubItems)
            {
                HazPackErrRow += " " + HazPackErrSub.Text + ",";
            }
            // Remove comma after last element of string.
            HazPackErrRow = HazPackErrRow.Substring(0, HazPackErrRow.Length - 2); 
            MessageBox.Show(HazPackErrRow); // List concatenated subitems
        }
Was it helpful?

Solution

Just don't add it in the first place?

foreach (ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
    {
        string HazPackErrRow = " ";

        bool first = true;
        foreach (ListViewItem.ListViewSubItem HazPackErrSub in HazPackErrItems.SubItems)
        {
            if (first) 
                first = false;
            else
                HazPackErrRow += " " + HazPackErrSub.Text + ",";
        }
        // Remove comma after last element of string.
        HazPackErrRow = HazPackErrRow.Substring(0, HazPackErrRow.Length - 2); 
        MessageBox.Show(HazPackErrRow); // List concatenated subitems
    }

OTHER TIPS

If you can use Linq, use String.Join(), it reads a lot easier:

    foreach (ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
    {
        string HazPackErrRow = string.Join(", ", HazPackErrItems.SubItems.Skip(1).Select(s => s.Text).ToArray())

        MessageBox.Show(HazPackErrRow); // List concatenated subitems
    }

This is based on Inferis's answer, but it uses a StringBuilder and avoids the need for the final Substring call:

foreach (ListViewItem errors in HazmatPackageErrorListview.Items)
{
    StringBuilder builder = new StringBuilder();

    bool first = true;
    foreach (ListViewItem.ListViewSubItem error in errors.SubItems)
    {
        if (first)
        {
            first = false;
        }
        else
        {
            if (builder.Length > 0)
            {
                builder.Append(", ");
            }
            builder.Append(error.Text);
        }
    }
    MessageBox.Show(builder.ToString()); // List concatenated subitems
}

Here's an alternative way of tackling the delimiter issue:

foreach (ListViewItem errors in HazmatPackageErrorListview.Items)
{
    StringBuilder builder = new StringBuilder();

    bool first = true;
    string prefix = "";
    foreach (ListViewItem.ListViewSubItem error in errors.SubItems)
    {
        if (first)
        {
            first = false;
        }
        else
        {
            builder.Append(prefix);
            prefix = ", ";
            builder.Append(error.Text);
        }
    }
    MessageBox.Show(builder.ToString()); // List concatenated subitems
}

Of course, there's a simpler way:

foreach (ListViewItem errors in HazmatPackageErrorListview.Items)
{
    string[] bits = errors.SubItems.Skip(1)
                          .Select(item => item.Text)
                          .ToArray();
    string errorLine = string.Join(", ", bits);
    MessageBox.Show(errorLine);
}

You can use IList<T>.Skip():

foreach (var HazPackErrSub in HazPackErrItems.SubItems.Skip(1))

Because other people seem to be rewriting your code, why not I? =]

foreach(ListViewItem HazPackErrItems in HazmatPackageErrorListview.Items)
{
    string HazPackErrRow = String.Join(", ", HazPackErrItems.SubItems.Skip(1).Select(t => t.Text).ToArray());

    MessageBox.Show(HazPackErrRow); // List concatenated subitems
}

If I understand the problem correctly, you could just use a for loop and start the index at 1 instead of 0.

add the comma at the beginning, then you only have to do one check, rather than a check on every iteration


string HazPackErrRow = "";
foreach (ListViewItem.ListViewSubItem HazPackErrSub in HazPackErrItems.SubItems)        
{
            HazPackErrRow +=  "," + " " + HazPackErrSub.Text;        
}
// Remove comma before first element of string.
if(HazPackErrRow.Length > 0)
 HazPackErrRow = HazPackErrRow.Substring(1);

Edit: Um, ignore me, I misread the question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top