4th time asking this question after trying to apply so fixes. My problem is I have 2 listboxs one holds IDs and the other holds Cell ids. The ID listbox has 10 items (for testing) and Cell boxes have 5 ID. I'm trying to process listId and listCell at the same time creating update links...
example MakeReq will create txtWebUpdate.Text listID listCell &ire=1, in which is
store.domain.com/101/sec01&ire=1
store.domain.com/102/sec02&ire=1
store.domain.com/103/sec03&ire=1
store.domain.com/104/sec04&ire=1
store.domain.com/105/sec05&ire=1
store.domain.com/106/sec01&ire=1 <- notice how listCell starts over it
continues to loop applying sections until the ListID is complete.
here's the code i've been working with. what's happening with my code is that it's only selecting the first item. It's not going to the next item after its done.
if (listId.Items.Count != 0 && listCell.Items.Count != 0)
{
for (int a = 0; a < listId.Items.Count; a++)
{
for (int b = 0; b < listCell.Items.Count; b++)
{
lblID.Text = listId.Items[a].ToString();
MakeReq(txtWebUpdate.Text + listId.Items[a].ToString() +
"&ire=1", listCell.Items[b].ToString());
//System.Threading.Thread.Sleep(5);
}
}
}
Please only comment if you can help. I'm almost positive that the problem is the for statement and how it's selecting list items, but I may be wrong.
Edit More Info: after testing an example/suggestion for #duffp below the problem is definitely with my For statements. What's happening is its counting that I have 5 entries in ListCell and then output one (the same) ListID 5times but with a different ListCell. Can someone help me write it following what I wrong above?
It may have something to do within the MakeReq method call. I just tried the following code:
private void Form1_Load(object sender, EventArgs e)
{
if (listId.Items.Count != 0 && listCell.Items.Count != 0)
{
for (int a = 0; a < listId.Items.Count; a++)
{
for (int b = 0; b < listCell.Items.Count; b++)
{
lblID.Text = listId.Items[a].ToString();
MakeReq(listId.Items[a].ToString(), listCell.Items[b].ToString());
}
}
}
}
public void MakeReq(string listId, string cellId)
{
Console.WriteLine("store.domain.com/" + listId + "sec01&ire=" + cellId);
}
And it gave the output:
store.domain.com/ID_10sec01&ire=Cell_1
store.domain.com/ID_10sec01&ire=Cell_2
store.domain.com/ID_10sec01&ire=Cell_3
store.domain.com/ID_10sec01&ire=Cell_4
store.domain.com/ID_10sec01&ire=Cell_5
store.domain.com/ID_10sec01&ire=Cell_6
store.domain.com/ID_10sec01&ire=Cell_7
store.domain.com/ID_10sec01&ire=Cell_8
store.domain.com/ID_10sec01&ire=Cell_9
store.domain.com/ID_10sec01&ire=Cell_10
Isn't that what you wanted?
I think there might be some side-effects in MakeReq that you are not showing us. How about adding some debug statements to your code, like this:
if (listId.Items.Count != 0 && listCell.Items.Count != 0)
{
for (int a = 0; a < listId.Items.Count; a++)
{
int listCellCount = listCell.Items.Count;
for (int b = 0; b < listCell.Items.Count; b++)
{
lblID.Text = listId.Items[a].ToString();
MakeReq(txtWebUpdate.Text + listId.Items[a].ToString() +
"&ire=1", listCell.Items[b].ToString());
//System.Threading.Thread.Sleep(5);
Debug.Assert(listCellCount == listCell.Items.Count);
}
}
}
The assertion (listCellCount == listCell.Items.Count) should always be true, unless something is changing listCell.Items.
Related
I have a method that iterate through a list and display the result of each type one followed by another meaning that I will display result from rd followed by result from cv followed by adz. But the actual method is very slow and it takes long time to retrieve back the results. what are the ways to improve the performance and will it matter using different data structure
private List<AllJobModel> GetAllJobModelsOrder(List<AllJobModel> result)
{
var countItems = result.Count;
List<AllJobModel> list = new List<AllJobModel>();
while (countItems != 0)
{
for (int i = 0; i < countItems; i++)
{
if (result.ElementAt(i).JobImage.Contains("rd"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
for (int i = 0; i < countItems; i++)
{
if (result.ElementAt(i).JobImage.Contains("cv"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
for (int i = 0; i < countItems; i++)
{
if (result.ElementAt(i).JobImage.Contains("adz"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
for(int i =0; i < countItems; i++)
{
if((!result.ElementAt(i).JobImage.StartsWith("rd") && !result.ElementAt(i).JobImage.StartsWith("adz")) && !result.ElementAt(i).JobImage.StartsWith("cv"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
}
return list;
}
This is a bad way to sort. You're effectively looping over the list 4 times, extracting specific groups of items each time. You also have a potential bug by removing items as you are iterating over the list. While there are many improvements you can make to your method, a better way would be to use OrderBy with the following sort condition:
list = result.OrderBy( m => m.JobImage.Contains("rd") ? 1 :
m.JobImage.Contains("cv") ? 2 :
m.JobImage.Contains("adz") ? 3 :
4)
.ToList();
Check out this link: https://cc.davelozinski.com/c-sharp/fastest-collection-for-string-lookups
Was very helpfull for me.
Regarding your specific problem. It looks like you're doing some filtering of the data. Linq has an easy way of doing that. I haven't test performance but if you can give me some example data ill try it for you. It could be something like this.
private List<AllJobModel> GetAllJobModelsOrder(List<AllJobModel> result)
{
return result.Where(x => x.JobImage.Contains("rd") || x.JobImage.Contains("cv") || x.JobImage.Contains("adz")).ToList();
}
My current code is inside a timer to keep comparing if all drones actual position is near desired position but I dont think this is the best approach because I think this leads to slow processing.
Is there a way to check if the actual position is near desired position without using peek inside a timer?
private void timer_missao_Tick(object sender, EventArgs e)
{
string[] pontos_separados = null;
for (int k = 0; k < drone.Length; k++)
{
if (queue[k].Count > 0)
{
if (queue[k].Peek() == "levantar")
{
drone[k]._droneClient.FlatTrim();
drone[k]._droneClient.Takeoff();
drone[k].subir_ate_altura = true;
queue[k].Dequeue();
}
else if (queue[k].Peek().Split(null)[0] == "goto")
{
pontos_separados = queue[k].Peek().Split(null)[1].Split(',');
drone[k].posicao_desejada = new PointF(Convert.ToSingle(pontos_separados[0]), Convert.ToSingle(pontos_separados[1]));
int precisao = 5;
if (drone.All(d=> d.pos_atual().X > d.pos_desej().X - precisao && d.pos_atual().X <d.pos_desej().X + precisao &&
d.pos_atual().Y > d.pos_desej().Y - precisao && d.pos_atual().Y < d.pos_desej().Y + precisao))
{
for (int i = 0; i < drone.Length; i++)
{
queue[i].Dequeue();
}
}
}
else if (queue[k].Peek() == "aterrar")
{
drone[k]._droneClient.Land();
if (drone[k]._droneClient.NavigationData.State == NavigationState.Landed)
{
queue[k].Dequeue();
}
}
You could do the check only when the drone positions are updated, and not on every tick. That way you can also skip the Peek, by having the code that updates the drone position pass the updated Drone object to your check function.
As a coding execise, I'm working on a visualisation of different sorting algorithms. I have a button that pauses the algorithm and shows every item of the array as a bar-diagramm. To achive this, I have a nested while-loop inside of the two for-loops for the sorting. It loops throug, until I press the button again, a boolean variable gets set to true and the sorting continues.
However, after the programm exits the while loop, the two indecies of the for-loops (i and j) get reset to 0 and the sorting starts from the beginning again.
swap() and draw() are custom functions that do pretty much exactly what the name suggests.
Here's my code for the sorting:
for (i = 0; i < items.Count(); i++)
{
for (j = 0; j < items.Count() - 1 - i; j++)
{
//lbl_i.Text = Convert.ToString(i);
//lbl_j.Text = Convert.ToString(j);
if (items[j] > items[j + 1])
{
swap(j, j + 1); //swaps the items at two given indecies
draw(); // draws the array to the picturebox
}
while (sorting == false) //the sorting is paused
{
Application.DoEvents();
}
}
}
Any idea why this could happen?
I have a suspition that it could be a problem with the Application.DoEvents()-call, but I need that so I can press the button.
Also, if you notice anything else in my code that I could do better, please let me know, I'm not very experienced at coding, so any help and constructive criticism is welcome. :-)
Thank You!
Benjamin
You don't create i and j in the for-loops, i and j might get changed somewhere else in your app. Try this:
for (int i = 0; i < items.Count(); i++)
{
for (int j = 0; j < items.Count() - 1 - i; j++)
{
//lbl_i.Text = Convert.ToString(i);
//lbl_j.Text = Convert.ToString(j);
if (items[j] > items[j + 1])
{
swap(j, j + 1); //swaps the items at two given indecies
draw(); // draws the array to the picturebox
}
while (sorting == false) //the sorting is paused
{
Application.DoEvents();
}
}
}
The change is in: int i, int j
Found the answer: The problem was, that I was calling this function from the same button in the first place. In its click-event, I have an if-statement to check if the button said "Pause" or "Start", but when i paused the programm, it said "Start" again. So when I click it, the function gets called again and int i and int j are reinitialised to 0.
Code in the click-event:
private void btn_start_Click(object sender, EventArgs e)
{
//new added code
if (btn_start.Text == "Start")
{
btn_start.Text = "Pause";
sorting = true;
sort();
}
else if (btn_start.Text == "Pause")
{
btn_start.Text = "Continue"; // '= "Start"' in the old code
tmr_sorting.Stop();
sorting = false;
}
// new added code
else if (btn_start.Text == "Continue")
{
btn_start.Text = "Pause";
sorting = true;
}
}
I want to remove multiple row from datagridview,
I tried the below code, here row's are getting deleted based on index.
for (int m = 0; m < dataGridView3.Rows.Count - 1; m++)
{
if (dataGridView3.Rows[m].Cells[2].Value != null)
{
for (int n = 0; n < dataGridView2.Rows.Count - 1; n++)
{
if (dataGridView2.Rows[n].Cells[2].Value != null)
{
if (dataGridView2.Rows[n].Cells[2].Value.Equals(dataGridView3.Rows[m].Cells[2].Value) &&
dataGridView2.Rows[n].Cells[8].Value.Equals(dataGridView3.Rows[m].Cells[8].Value))
{
dataGridView2.Rows.RemoveAt(n);
//break;
}
}
}
}
}
here rows are not getting deleted properly, because index is changed after every single delete, so some records are missing out from loop.
can anyone help me how to solve this?
If you're going to remove items from the collection as you iterate through it like this, you'll need to work backwards through the collection of rows:
// start with the last row, and work towards the first
for (int n = dataGridView2.Rows.Count - 1; n >= 0; n--)
{
if (dataGridView2.Rows[n].Cells[2].Value != null)
{
if (dataGridView2.Rows[n].Cells[2].Value.Equals(dataGridView3.Rows[m].Cells[2].Value) &&
dataGridView2.Rows[n].Cells[8].Value.Equals(dataGridView3.Rows[m].Cells[8].Value))
{
dataGridView2.Rows.RemoveAt(n);
//break;
}
}
}
Alternatively, you could use LINQ to find your matches first, and then remove them:
var rowToMatch = dataGridView3.Rows[m];
var matches =
dataGridView2.Rows.Cast<DataGridViewRow>()
.Where(row => row.Cells[2].Value.Equals(rowToMatch.Cells[2].Value)
&& row.Cells[8].Value.Equals(rowToMatch.Cells[8].Value))
.ToList();
foreach (var match in matches)
dataGridView2.Rows.Remove(match);
Just to make it less of a maintenance head-ache, you might want to use the column name instead of the column index too... just a thought.
I want to add the exact value of textbox into datagridview my problem is if i will add another item the last item I add will also change. Here is the print screen of sample problem..
1st try
2nd try
This is my code.
int n = dataGridView3.Rows.Add();
for (int j = 0; j < dataGridView3.RowCount; j++)
{
if (dataGridView3.Rows[j].Cells[1].Value != null && (textBox4.Text == dataGridView3.Rows[j].Cells[4].Value.ToString()))
{
MessageBox.Show("Item Already on List!");
dataGridView3.Rows.Remove(dataGridView3.Rows[n]);
return;
}
else
{
dataGridView3.Rows[j].Cells[1].Value = textBox43.Text;
dataGridView3.Rows[j].Cells[4].Value = textBox4.Text;
dataGridView3.Rows[j].Cells[2].Value = DateTime.Now.ToShortDateString();
dataGridView3.Rows[j].Cells[3].Value = dateTimePicker3.Text;
dataGridView3.FirstDisplayedScrollingRowIndex = n;
dataGridView3.CurrentCell = dataGridView3.Rows[n].Cells[0];
dataGridView3.Rows[n].Selected = true;
}
}
You are looping over the complete array and if it is not yet on the list it goes in to the else part of your if. In that block you assign the current entered values to your row, for every single row you already have.
To fix that I separated the Check for duplicates and the Add part more clearly.
Do notice that if you would have run this through the debugger and stepped on each line of your code (hitting F10 in Visual Studio) you would have spotted this bug easily. Have a look at the blog from Scott Guthrie (among others) http://weblogs.asp.net/scottgu/debugging-tips-with-visual-studio-2010
// check if we already added that one
for (int j = 0; j < dataGridView3.RowCount; j++)
{
if (dataGridView3.Rows[j].Cells[1].Value != null && (textBox4.Text == dataGridView3.Rows[j].Cells[4].Value.ToString()))
{
MessageBox.Show("Item Already on List!");
return;
}
}
// lets add it!
int n = dataGridView3.Rows.Add();
dataGridView3.Rows[n].Cells[1].Value = textBox43.Text;
dataGridView3.Rows[n].Cells[4].Value = textBox4.Text;
dataGridView3.Rows[n].Cells[2].Value = DateTime.Now.ToShortDateString();
dataGridView3.Rows[n].Cells[3].Value = dateTimePicker3.Text;
dataGridView3.FirstDisplayedScrollingRowIndex = n;
dataGridView3.CurrentCell = dataGridView3.Rows[n].Cells[0];
dataGridView3.Rows[n].Selected = true;