If ListView Column "x" Contains "value" - c#

This is embedded in another loop, and well, it's pretty slow. Is there a better way to do this?
for(int i=0;i< listView.Items.Count;i++)
{
if(listView.Items[i].SubItems[3].Text == "asdf")
{
}
}

Well there's a nicer way to do it:
foreach (ListViewItem item in listView.Items)
{
if (item.SubItems[3].Text == "asdf")
{
...
}
}
Or you could use LINQ:
var query = listView.Items
.Cast<ListViewItem>()
.Where(item => item.SubItems[3].Text == "asdf");
foreach (var item in query)
{
...
}
I doubt that that will be faster though...
Does your outer loop change the listView? If not, could you do the query once and reuse the results in the outer loop?

In case someone runs across this using WPF, you don't get .SubItems on item when you use foreach (ListViewItem item in listView.Items). Instead, I found I could just use DataRowView and get the value of the cell that way:
foreach (DataRowView drv in listView.Items)
{
if (drv.Row[3].ToString() == "asdf")
{
...
}
}
You do have to add a using System.Data; statement at the top of your class to use it. I found it worked in WPF, and it might in other areas (i.e. WinForms), as well.

Related

Query too large mongodb c#

I`m trying to make a query in robomongo but there seems to be too many results in the query.
List<DataObject> list = collection.FindAs<DataObject>(Query.EQ("Item1", "Value1")).ToList();
foreach (DataObject item in list)
{
//Do Something
}
From what i read, i would need to use MongoCursor, but I couldnt find a good example, is there iterate through everything using batches of 1000?
Something like:
MongoCursor<DataObject> cursor = collection.FindAs<DataObject>(Query.EQ("Item1", "Value1"));
int batchNumber = 1000;
List<DataObject> list;
while(list = cursor.getBatch(batchNumber);)
{
foreach (DataObject item in list)
{
//Do Something
}
}
Now I understood i could easily solve this if i dont save it in a list before the foreach by doing :
foreach (DataObject item in collection.FindAs<DataObject>(Query.EQ("Item1", "Value1")))
{
//Do Something
}
This was solved by not saving the result in a list before the foreach. Like this
foreach (DataObject item in collection.FindAs<DataObject>(Query.EQ("Item1", "Value1")))
{
//Do Something
}

How do I find out if individual items in CheckedListBox are checked? C#

I've tried looking in checkedListBox1.Items, but that didn't help. So how do I check if an item in a CheckedListBox is marked? It's in a windows forms application.
You can get a list of checked items using CheckedItems property.
Example 1:
foreach (var item in this.checkedListBox1.CheckedItems)
{
MessageBox.Show(item.ToString());
}
Example 2:
this.checkedListBox1.CheckedItems.Cast<object>()
.ToList()
.ForEach(item =>
{
//do stuff here
//for example
MessageBox.Show(item.ToString());
});
If you are sure items are string for example, you can use Cast<object> in above code.
You can get the list of checked indices using CheckedIndices property.
Example:
this.checkedListBox1.CheckedIndices.Cast<int>()
.ToList()
.ForEach(index =>
{
//do stuff here
//for example
MessageBox.Show(this.checkedListBox1.Items[index].ToString());
});
try this:
foreach (ListItem item in checkedListBox1.Items)
{
if (item.Selected)
{
// If the item is selected
}
else
{
// Item is not selected, do something else.
}
}

Load arraylist into a TextBox

I have another question and I can't seem to find anything on Google.
What this program does
This program displays the information from an RSS feed.
Question
How can I load all the items from an Arraylist to a TextBox?
Things I have tried
This is what I have so far:
List<Array> list1 = new List<Array>();
foreach (var item in list1)
{
textBox1.AppendText(item.ToString());
}
Problem
When I do this, the TextBox shows this:
System.String[]System.String[]
Instead of:
Recommended Build for CraftBukkit: 1.2.4-R1.0 (build 2126)
http://dl.bukkit.org/downloads/craftbukkit/view/00993_1.2.4-R1.0/
Does anybody have any idea how this array stuff work?
Do I need to loop through the array and search for specific indexes?
Sorry, but I'm still a little bit new to C#, and sorry for my English I'm Dutch :<.
It looks like you ArrayList contains array of string instead of string. So try this :
foreach (var item in list1.OfType<string[]>().SelectMany(i => i))
{
textBox1.AppendText(item);
}
It seems that item is a string array, so try to implode it:
foreach (var item in list1)
{
textBox1.AppendText(string.Join("", item));
}
Your code is basically a list of array. That's why it is showing system.string[]
Change it to
foreach (var item in list1)
{
textBox1.AppendText(string.Join("", item));
}
It will join your each string[] (i.e. item) in List<> and create it like
firstarrrayfirstitem, firstarrayseconditem
and textbox as
firstarrrayfirstitem, firstarrayseconditem, secondarrayfirstitem, secondarrayseconditem.... and so on.
A better way could be to use a stringbuider for better performance and reduction in a propertychanged event called by the textbox;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (var item in list1.OfType<string[]>().SelectMany(i => i))
{
sb.Append(item);
}
textBox1.Text = sb.ToString();
Better way:
textBox1.Text = string.Join("", list1.OfType<string[]>().SelectMany(i => i));

foreach loop from multiple arrays c#

This should be a simple question. All I want to know is if there is a better way of coding this. I want to do a foreach loop for every array, without having to redeclare the foreach loop. Is there a way c# projects this? I was thinking of putting this in a Collection...?
Please, critique my code.
foreach (TextBox tb in vert)
{
if (tb.Text == box.Text)
conflicts.Add(tb);
}
foreach (TextBox tb in hort)
{
if (tb.Text == box.Text)
conflicts.Add(tb);
}
foreach (TextBox tb in cube)
{
if (tb.Text == box.Text)
conflicts.Add(tb);
}
You can use LINQ:
conflicts.AddRange(
vert.Concat(hort).Concat(cube)
.Where(tb => tb.Text == box.Text)
);
I'm assuming that conflicts is a List<TextBox>, which has an AddRange method. If it isn't, you'll need to call Add in a (single) loop.
If you're creating conflicts, (or if it starts empty), you can call .ToList() instead.
Another .net 3.5 approach:-
conflicts.AddRange(from textBox in vert.Concat(hort).Concat(cube)
where textBox.Text == box.Text
select textBox);
If you can't use LINQ for whatever reason (and I highly suggest you do) you could make your array searching a single method. For example:
public void FindConflicts(IEnumerable<TextBox> tbList, IList<TextBox> conflicts, string test)
{
foreach(TextBox tb in tbList)
{
if(tb.Text == test)
{
conflicts.Add(tb);
}
}
}
And then call it like so:
FindConflicts(vert, conflicts, box.Text);
FindConflicts(hort, conflicts, box.Text);
FindConflicts(cube, conflicts, box.Text);
There are of course many ways to write this, but you could also do
foreach (var direction in new[] { vert, hort, cube })
foreach (TextBox tb in direction)
if (tb.Text == box.Text)
conflicts.Add(tb);
var unionResult = vert.Concat(hort).Concat(cube)
foreach(TextBox tb in unionResult)
if(tb.Text == box.Text)
conflicts.Add(tb);
You should be able to use Enumerable.Concat to glue them together if you're using .Net 3.5 or higher.
foreach (TextBox tb in vert.Concat(hort).Concat(cube))
If you try to create Sudoku game(mentioned in comments) first read about Permutation group and Combinatorics.
This will help you to choose more efficient Application Model w/o using foreach on text boxes. Using lazy computation resolve the problem with object reduction but not improve your logics man.

Help with converting foreach loop to while loop in c#

I had learnt by reading your great answers here, that it is not good practice deleting items from within a foreach loop, as it is (and I quote) "Sawing off the branch you're sitting on".
My code currently removes the text from the dropdownlist, but the actual item remains (just without text displayed).
In other words, it isn't deleting, and probably can't because you can't delete from within a foreach loop.
After hours of trying I am unable to get my head around a way of doing it.
//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
//this is the foreach loop
foreach (ToolStripItem mItem in favoritesToolStripMenuItem.DropDownItems)
{
//This rules out seperators
if (mItem is ToolStripMenuItem)
{
ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;
//This matches the dropdownitems text to the CheckedItems String
if (((ToolStripMenuItem)mItem).Text.ToString() == organizeFav.CheckedItems[i].ToString())
{
//And deletes the item
menuItem.DropDownItems.Remove(mItem);
}
}
}
}
But it isn't deleting because it is within a foreach loop!
I would greatly appreciate your help, and be truly amazed if anyone can get their head around this code :)
Kind Regards
Fun with LINQ!
// Loop through the checked items, same as you did.
foreach (var checkedItem in this.organizeFav.CheckedItems)
{
// Cast from IEnumerable to IEnumerable<T> so we can abuse LINQ
var matches = favoritesToolStripMenuItem.DropDownItems.Cast<ToolStripItem>()
// Only items that the Text match
.Where(item => item.Text == checkedItem.Text)
// Don't match separators
.Where(item => item is ToolStripMenuItem)
// Select the keys for the later .Remove call
.Select(item => item.Name);
// Loop through all matches
foreach (var key in matches)
{
// Remove them with the Remove(string key) overload.
favoritesToolStripMenuItem.Remove(key);
}
}
You don't need a foreach loop - just use a regular loop but go in reverse, start at the end and go to the beginning.
//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
//this *replaces* the foreach loop
for(int j = favoritesToolStripMenuItem.DropDownItems.Count - 1; j >= 0; j--)
{
ToolStripMenuItem menuItem = favoritesToolStripMenuItem.DropDownItems[j] as ToolStripMenuItem;
//This rules out seperators
if (menuItem != null)
{
//This matches the dropdownitems text to the CheckedItems String
if (menuItem.Text.ToString() == organizeFav.CheckedItems[i].ToString())
{
favoritesToolStripMenuItem.DropDownItems.Remove(menuItem);
}
}
}
}
this was #Kurresmack's code rearranged, i just coded it directly here in the page so excuse any small syntax error or anything obvious i overlooked (disclaimer: it is a sample!!)
You can still treat favoritesToolStripMenuItem.DropDownItems as a collection like you were, but you don't have to enumerate over it using a foreach. This cuts down on a few lines of code, and it works because you are iterating it in reverse order, you will not get an index out of bounds exception.
Try something like this:
//For each checked box, run the delete code
for (int i = 0; i < this.organizeFav.CheckedItems.Count; i++)
{
List<ToolStripItem> toRemove = new List<ToolStripItem>();
//this is the foreach loop
foreach (ToolStripItem mItem in favoritesToolStripMenuItem.DropDownItems)
{
//This rules out seperators
if (mItem is ToolStripMenuItem)
{
ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;
//This matches the dropdownitems text to the CheckedItems String
if (((ToolStripMenuItem)mItem).Text.ToString() == organizeFav.CheckedItems[i].ToString())
{
toRemove.Add(mItem);
}
}
}
foreach(var item in toRemove)
{
favoritesToolStripMenuItem.DropDownItems.Remove(item);
}
}
To my mind, the way to make the code work is:
1. Create an instance of the type the favoritesToolStripMenuItem.DropDownItems collection is.
2. In the foreach loop, add all items, you do not want to be removed, to that collection.
3. Make favoritesToolStripMenuItem.DropDownItems to point to the new collection. Or clear favoritesToolStripMenuItem.DropDownItems and load the items from the new collection to it.
Hope this helps
Instead of a foreach use a reverse for-Loop:
for(int reverseIndex = myList.Count - 1; reverseIndex >= 0; reverseIndex--)
{
var currentItem = myList[reverseIndex];
if(MatchMyCondition(currentItem))
{
myList.Remove(currentItem);
}
}

Categories