foreach loop question - c#

Is there any other shorter/more efficient way to check and see if it is the last item in my ListBox? The main goal here is basically to add the selected items to a label, and add a comma after every one but the last one. Any suggestions?
int sc = 0;
List<string> interestitems = new List<string>();
foreach (ListItem siitem in ListBox1.Items)
{
if (siitem.Selected == true)
{
interestitems.Add(siitem.Value.ToString());
}
}
foreach (string inteitem in interestitems)
{
Label1.Text += inteitem;
sc++;
if (sc < interestitems.Count)
{
Label1.Text += ",";
}
}

Instead of your second loop just use:
Label1.Text = string.Join("," , interestitems);
P.S.
if you're using .net 3.5, you need to pass an array of strings to string.Join(), then :
Label1.Text = string.Join("," , interestitems.ToArray());
EDIT:
If you want to completely avoid looping just do:
var selItems = ListBox1.Items.Cast<ListItem>()
.Where(item => item.Selected)
.Select(item => item.ToString());
Label1.Text = string.Join("," , selItems);

How about LINQ:
Label1.Text = string.Join(
",",
ListBox1.Items
.OfType<ListItem>()
.Where(item => item.Selected)
.Select(x => x.Value.ToString())
.ToArray()
);

You can replace all of your code with some LINQ:
Label1.Text = String.Join(", ",
ListBox1.Items.Cast<ListItem>()
.Where(i => i.Selected)
.Select(i => i.Value.ToString())
);
In .Net 3.5, you'll need to add .ToArray().

I believe you can do this:
interestitems.IndexOf(inteitem);
Altought it worked me with other item types, may give you an idea. I haven't checked if it works with strings.
The you just have to eliminate the last one, with the index check if it's the last ones with interestitems.Count

Why not just build up the string as you iterate during the first loop
var builder = new StringBuilder();
var first = true;
foreach (var item in ListBox1.Items) {
if (item.Selected) {
if (!first) {
builder.Append(", ");
}
first = false;
builder.Append(item.Value.ToString());
}
}
Label1.Text = builder.ToString();

Related

How can I convert this foreach into a List.ForEach

I have the following foreach loop:
var myString = "";
foreach (var item in myList)
{
myString += GetItems(item.ID);
}
Can this be converted to a List.ForEach. I was trying to do something like this:
myList.ForEach(s => GetItems(s.ID));
But I'm not sure how to return a string with concatenated ids this way.
string.Join("", myList.Select(item => item.GetItems(item.Id));
What about aggregate?
var res= myList.Aggregate(
new StringBuilder(),
(b,s)=> b.Append(s)).ToString()
Use can use this also :
items.Select(i => i.Boo).Aggregate((i, j) => i + delimiter + j)
you can see this answer

Showing the result once

I have the following code that shows my result in Messagebox but it shows each time only one ifi want to see the next one,I must click OK on message box to see the next. I want to see all result at the same time. May you comments your idea?
foreach (var resultwithindexss in resultss.Select((rr, iindex) => new { result2 = rr, Index = iindex }).OrderByDescending(rr => rr.result2).Take(number))
{
MessageBox.Show(string.Format("{0}: {1}", resultwithindexss.Index, resultwithindexss.result2));
}
PS: I tried the following code, But show no result.
System.Console.WriteLine(string.Format("{0}: {1}", resultwithindexss.Index, resultwithindexss.result2));
Thanks in advance
Use a StringBuilder to build "big" message and then display it
var sb = new StringBuilder();
foreach (var resultwithindexss in resultss
.Select((rr, iindex) => new { result2 = rr, Index = iindex })
.OrderByDescending(rr => rr.result2)
.Take(number))
{
sb.AppendFormat("{0}: {1}", resultwithindexss.Index, resultwithindexss.result2));
sb.AppendLine();
}
MessageBox.Show(sb.ToString());
It's because you're extracting every result and display it instantly instead of adding it to a string and after the loop to display it.
This should do the trick(have not tested it):
var sb = new StringBuilder("");
foreach (var resultwithindexss in resultss.Select((rr, iindex) => new { result2 = rr, Index = iindex }).OrderByDescending(rr => rr.result2).Take(number))
{
sb.AppendFormat(string.Format("{0}: {1}\r\n", resultwithindexss.Index, resultwithindexss.result2));
}
MessageBox.Show(sb.ToString());

how to loop over generic List<T> and group per 3 items

I want to loop over a generic list of MemberProfiles:
List<MemberProfile> jobseekers
, and group the items in a <div class='group'>tag. Every <div class="group"> should contain 3 jobseekers like this:
<div class="group">
<div class="jobseeker">
...data jobseeker
</div>
</div>
I tried different methods on generic list, like .skip() and .take() but I'm not succeeding in implementing this scenario.
My code looks like this:
foreach (MemberProfile jobseekerProfile in Jobseekers)
{
if (jobseekerProfile != null)
{
Label lblJobseeker = new Label();
StringBuilder sbJobseeker = new StringBuilder();
sbJobseeker.Append(string.Format("<p><strong>{0} {1}</strong><br />", jobseekerProfile.FirstName, jobseekerProfile.LastName));
XPathNodeIterator preValues = library.GetPreValues(1362);
preValues.MoveNext();
XPathNodeIterator iterator2 = preValues.Current.SelectChildren("preValue", "");
while (iterator2.MoveNext())
{
if (jobseekerProfile.JobType == iterator2.Current.GetAttribute("id", ""))
{
sbJobseeker.Append(string.Format("looking for a {0}<br />", iterator2.Current.Value));
}
}
XPathNodeIterator iterator3 = library.GetPreValues(1363);
iterator3.MoveNext();
XPathNodeIterator iterator4 = iterator3.Current.SelectChildren("preValue", "");
StringBuilder sbJobExperience = new StringBuilder();
string[] strJobExperience = jobseekerProfile.JobExperience.Split(new char[] { ',' });
int counter = 1;
while (iterator4.MoveNext())
{
if (jobseekerProfile.JobExperience.Contains(iterator4.Current.GetAttribute("id", "")))
{
if (counter != strJobExperience.Count<string>())
{
sbJobExperience.Append(string.Format("{0}, ", iterator4.Current.Value));
counter++;
}
else
{
sbJobExperience.Append(string.Format("{0}", iterator4.Current.Value));
}
}
}
sbJobseeker.Append(string.Format("Fields of experience: {0}<br />", sbJobExperience.ToString()));
sbJobseeker.Append(string.Format("Years of experience: {0}<br />", jobseekerProfile.YearsExperience));
sbJobseeker.Append(string.Format("Country: {0}<br />", jobseekerProfile.Country));
sbJobseeker.Append(string.Format("<form name='frmSelect' action='/selectjobcandidate.aspx' method='post'><input type='hidden' name='username' value='{0}' /><input type='submit' value='select candidate' /></form>", jobseekerProfile.UserName));
lblJobseeker.Text = sbJobseeker.ToString();
phListJobseekers.Controls.Add(lblJobseeker);
}
}
can someone put me on the right track to implement this scenario?
for (var i = 0; i < Jobseekers.Count; i += 3)
{
foreach (MemberProfile jobseekerProfile in Jobseekers.Skip(i).Take(3))
{
}
}
Is this what you are after?
Since you seem to want to do it with linq, here we go:
var tagged = Jobseekers.Select((x, i) => new { x, i });
var grouped = tagged.ToLookup(t => (t.i - 1) / 3, t => t.x);
foreach (var group in grouped)
{
Console.WriteLine("Group:");
foreach (var item in group)
{
Console.WriteLine(item);
}
}
From the following answer : Split List into Sublists with LINQ
public static List<List<MemberProfile>> Split(List<MemberProfile> source)
{
return source
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / 3)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
See other answers as well
Your question isn't completely clear, but it appears that you want to split your jobseekers list into groups of 3 elements each, and then perform some manipulation on each group of 3 to get some HTML snippet, so the output is a sequence of HTML snippets.
Let's assume that jobseekers always has a multiple of 3 elements. If it doesn't always have 3 elements, this solution will leave the last group with the remainder of the elements, and you can filter out that group by dropping any group with fewer than 3 elements (that Where would go just after the GroupBy). With LINQ:
IEnumerable<string> htmlSnippets = jobseekers
.Zip(Enumerable.Range(0, jobseekers.Count), Tuple.Create)
.GroupBy(tup => tup.Item2 / 3)
.Select(GenerateHtmlString);
string combinedHtmlString = string.Join(string.Empty, htmlSnippets);
public string GenerateHtmlString(IEnumerable<MemberProfile> profiles)
{
return string.Format(#"<div class=""jobseeker"">{0}</div>",
// The question doesn't specify how the 3 jobseekers are rendered in HTML
);
}

How to covert IpAddress items to string c#

I have a ListBox that contains a System.net.IPAddress and string items. I want to convert them all to strings. I have tried this as shown below but it says it can not cast from IPAddress to string.
var List4 = f.listBox4.Items.Cast<String>().ToList();
foreach (string i in List4)
{
cursheet.get_Range(colname + x).Value = i;
x++;
}
var List4 = f.listBox4.Items.Cast<object>().Select(x => x.ToString())
How about this? No need for linq, casting, etc..
foreach (var item in f.listBox4.Items)
{
cursheet.get_Range(colname + x).Value = item.Text;
x++;
}
Or, if you want the value:
foreach (var item in f.listBox4.Items)
{
cursheet.get_Range(colname + x).Value = item.Value;
x++;
}

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

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
}
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
}
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.

Categories