C# string manipulation - How to remove the first element of each concatenated string in a collection
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
}
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.