Counting in lists with conditional statements - c#

I know this is a common topic but I have been through most of the threads here on Stackoverflow and having followed them, can't see to get mine to satisfy all conditions.
I want to return the 2nd item in a list and if the list is null or only has 1 item in it, return 0;
I have this:
public int practice(List<int> items)
{
if (items == null)
{
return 0;
}
else if (items.Count == 1)
{
return 0;
}
else
{
int second_place = items[1];
return second_place;
}
}
I can't get this to work if the list has only 1 item in it. It just bypasses my else if condition and then fails.
I have tried items.Count and items.Count() but it doesn't seem to make a difference.

Instead of adding another else condition, you could just combine them as follows:
public int practice(List<int> items)
{
if (items == null || items.Count <= 1)
{
return 0;
}
else
{
int second_place = items[1];
return second_place;
}
}

Ok so I figured out what I wasn't doing correct. The code wasn't passing if the list had 0 items in it (but was not null).
So I added another else if statement to handle that:
else if (items.Count == 0)
{
return 0;
}
And then it passed. I didn't originally do this because I had not initially thought of the case where the list is not null but has 0 items in it. I was incorrectly thinking it had either a value of null or 1 item or greater.

Related

How to overcome the ArgumentException while sorting using the IComparer interface in C#?

I'm sorting an array of RowRanges using the IComparer. It works fine when the row range is upto 16. Beyond 16, the exception occurs stating that, sorting is not performed and the exception is thrown stating that Soting cannot be performed, because the values compared to itself and a value is compared repeatedly to other. While debugging , I found that the issue occurs during objects taken for for comparison. But how is that exception occurs after 16, while it is working fine upto 16? Please refer to the below code snippet.
internal class ColComparer : IComparer
{
public int Compare(object a, object b)
{
if (a == null || b == null)
{
return System.Collections.Comparer.Default.Compare(a, b);
}
GridRangeInfo r0 = (GridRangeInfo)a;
GridRangeInfo r1 = (GridRangeInfo)b;
if (r0 == r1)
{
return 0;
}
else
{
if (r0.RangeType == GridRangeInfoType.Table)
{
return -1;
}
else if (r1.RangeType == GridRangeInfoType.Table)
{
return 1;
}
else if (r0.RangeType == GridRangeInfoType.Rows)
{
return -1;
}
else if (r1.RangeType == GridRangeInfoType.Rows)
{
return 1;
}
else if (r0.Left != r1.Left)
{
return r0.Left - r1.Left;
}
else if (r0.Right != r1.Right)
{
return r0.Right - r1.Right;
}
else if (r0.Top != r1.Top)
{
return r0.Top - r1.Top;
}
else
{
return r0.Bottom - r1.Bottom;
}
}
}
}
class SortArray
{
//Array Data
//
GridRangeInfo[] ranges = new GridRangeInfo[this.Count];
Array.Sort(ranges, new GridRangeInfo.ColComparer());
}
Let me know where the exception occurs and share your ideas to resolve this.
Thanks in Advance,
Sindhu
The conditions such as r0.RangeType == GridRangeInfoType.Table .. return -1 produce a non-stable result. This is because it depends on "which" item is r0 and r1.
Follow the same if-then-return pattern as with the rest of the function - where r0.X is compared to r1.X and then 'something is done based on that'.
eg.
if (r0.RangeType != r1.RangeType) {
{
if (r0.RangeType == GridRangeInfoType.Table) {
return -1; // r0 first - prioritize 'Table' range types
} else {
return 1; // r1 first
}
}

.NET IComparer sort error

I have run into a very weird issue recently. I deployed a new version of a program and am receiving this error when the IComparer.Compare() method gets called internally:
Unable to sort because the IComparer.Compare0 method returns inconsistent
results. Either a value does not compare equal to itself, or one value repeatedly
compared to another value yields different results. x:",x's type: 'String',
IComparer.".
The odd thing is that I cannot reproduce this issue on my computer. It doesn't happen for me in Visual Studio 2013 (debug or release versions) and it doesn't happen when I install the application either. To make things weirder, it doesn't even happen on every computer in production, only about 30% of them.
My application targets .NET Framework 4 and the platform target is x86.
There is only one instance of an IComparer object in my code, here it is:
public int Compare(string stringOne, string stringTwo)
{
if (stringOne == stringTwo) { return 0; }
else if (stringOne == null) { return stringTwo == null ? 0 : -1; }
else if (stringTwo == null) { return stringOne == null ? 0 : 1; }
else if (stringOne.StartsWith("_") && !stringTwo.StartsWith("_"))
{
return -1;
}
else if (!stringOne.StartsWith("_") && stringTwo.StartsWith("_"))
{
return 1;
}
else if ((stringOne.StartsWith("l") || stringOne.StartsWith("L")) &&
(!stringTwo.StartsWith("l") || !stringTwo.StartsWith("L")))
{
return -1;
}
else if ((!stringOne.StartsWith("l") || !stringOne.StartsWith("L")) &&
(stringTwo.StartsWith("l") || stringTwo.StartsWith("L")))
{
return 1;
}
else
{
if (stringTwo == null) { return 1; }
else { return stringOne.CompareTo(stringTwo) == 1 ? -1 : 1; }
}
}
Has anyone else had this issue and found a solution to it? Does my comparer look it covers all cases? I am totally lost about this issue and have no idea what to try next. Any help will be greatly appreciated.
This
else if ((stringOne.StartsWith("l") || stringOne.StartsWith("L")) &&
(!stringTwo.StartsWith("l") || !stringTwo.StartsWith("L")))
{
return -1;
}
else if ((!stringOne.StartsWith("l") || !stringOne.StartsWith("L")) &&
(stringTwo.StartsWith("l") || stringTwo.StartsWith("L")))
{
return 1;
}
should be
else if ((stringOne.StartsWith("l") || stringOne.StartsWith("L")) &&
!(stringTwo.StartsWith("l") || stringTwo.StartsWith("L")))
{
return -1;
}
else if (!(stringOne.StartsWith("l") || stringOne.StartsWith("L")) &&
(stringTwo.StartsWith("l") || stringTwo.StartsWith("L")))
{
return 1;
}
As a side note, the way you wrote this comparer function is highly ineffecient.

Deleting a node from an xmlNodeList

here is my code
public bool limitOutput()
{
double lowerLeftPointX = m_mapControl.CurrentExtent.LowerLeftPoint.X;
double lowerLeftPointY = m_mapControl.CurrentExtent.LowerLeftPoint.Y;
double upperRightPointX = m_mapControl.CurrentExtent.UpperRightPoint.X;
double upperRightPointY = m_mapControl.CurrentExtent.UpperRightPoint.Y;
for(int i = locationElements.Count - 1; i >= 0; i--)
{
if (Double.Parse(locationElements[i]["GEOMETRY_X"].InnerText) < lowerLeftPointX || Double.Parse(locationElements[i]["GEOMETRY_X"].InnerText) > upperRightPointX || Double.Parse(locationElements[i]["GEOMETRY_Y"].InnerText) < lowerLeftPointY || Double.Parse(locationElements[i]["GEOMETRY_Y"].InnerText) > upperRightPointY)
{
locationElements[i].ParentNode.RemoveChild(locationElements[i]);
}
}
if (locationElements.Count == 0)
{
PearMessageBox.Show(PearMessageBox.mBoxType.simpleNotification, "No results found in specified area");
return false;
}
return true;
}
I am trying to delete all the nodes which are not within the boundary I have set. The delete line is executed but does not actually delete as when I count locationElements it is still the same value before the method is executed.
Any ideas what is wrong with the code
The problem is due to the fact that RemoveChild() removed the element from the source XmlDocument, but not from the pre-populated XmlNodeList. So you need to execute again the code that was used to pre-populate locationElements variable, something like this :
//assume that GetLocationElements() is a method...
//...containing the same logic you used to populate locationElements variable
var updatedLocationElements = GetLocationElements();
if (updatedLocationElements.Count == 0)
{
PearMessageBox.Show(PearMessageBox.mBoxType.simpleNotification, "No results found in specified area");
return false;
}
return true;

break in a if else loop with a counter C#

I have a logic like below and i have a counter
if(condition1 == true)
{
// do something
if (counter==1)
{
// break and go to last else statement
}
}
else if (condition2==true)
{
if (counter == 2)
{
// break and go to last else statement
}
// do something
}
else
{
// do this
}
how do i use break in this logic ?
i tried putting goto tag for else but apparently it is not valid . and i want to avoid switch as there is too much logic.
counter will be 2 in second if else loop and if counter = 2 then first if and secong if else should execute if counter=3 then first if second if else third if else should execute ans so on –
Note: Question was changed, this answer is meanwhile incorrect!
You can change the if/else if to include the counter. Then you don't need a break or goto:
if (condition1 && counter != 1)
{
// do something
}
else if (condition2 && counter != 2)
{
// do something
}
else
{
// do this
}
use something like
if (condition1 && ( counter != 1 || counter != 2 || .... counter!= n )
{
// do something
}
else if (condition2 && (counter != 2 || .. || counter!= n )
{
// do something
}
and so on
else
{
// do this
}
Apart from the fact that a break statement doesn't jump outside an if condition, your code could be
refactored in a more simple way (just pretend that the closed brace after the first if it's only a typo)
if(condition1 ==true && counter != 1)
{
do something
}
else if (condition2==true && counter != 2)
{
do something
}
else
{
do this
}
I suspect that your algorithm could be entirely redesigned, but without more context that's impossible to know.
In the meantime, you can refactor your final else clause into a separate method. You don't actually need to use break (which isn't valid in an if statement anyway), with judicious use of else.
private void MyMethod()
{
if(condition1)
{
// do something
if (counter==1)
{
MyOtherMethod();
}
}
else if (condition2)
{
if (counter == 2)
{
MyOtherMethod();
}
else
{
// do something
}
}
else
{
MyOtherMethod()
}
}
private void MyOtherMethod()
{
// Do what was in your final else clause.
}
Prior to your question edits that moved the `do something' in the first if clause to before the counter check, this would have worked too:
Assuming your various "do something" statements were different things:
if (condition1 && counter != 1)
{
// Do something.
}
else if (condition2 && counter != 1)
{
// Do something.
}
else
{
// Do something else.
}
Just put the logic in the last else block in a seperate function which you can call whenever / wherever you want.
Don't. Using a break and continue in such a big loop adds complexity and clutters your logic.
If a loop is getting too big, use one or more well-named function calls within the loop instead.
bool myCondition = false;
if(condition1 ==true)
{
if (counter==1){myCondition = true;}
// do something
}
else if (condition2==true)
{
if (counter==1){myCondition = true;}
// do something
}
// so on
if(myCondition)
{
// do this
}

C# gives NullReferenceException while processing lists

The following code gives a NullReferenceException while processing. Can anyone tell me why its happening, and how to fix it? thanks in advance! this might be a very simple thing, I'm missing somewhere.
if (a.Count != 0)
{
foreach(DataGridViewRow row in a )
{
foreach (DataGridViewRow newrow in b)
{
if( row.Cells[0].Value.ToString() == newrow.Cells[0].Value.ToString() &&
row.Cells[1].Value.ToString() == newrow.Cells[1].Value.ToString()) // this is the line that gives the error.
{
a.Remove(row);
}
}
}
}
the two lists have been declared at the top of the class so I don't know why its giving this error.
List<DataGridViewRow> a = new List<DataGridViewRow>();
List<DataGridViewRow> b = new List<DataGridViewRow>();
As suggested, I tried using a for loop bit it still gives the same exception
here's the code
if (a.Count != 0)
{
for (int i = a.Count - 1; i >= 0; i--)
{
int index1 = i;
for (int k = 0; k < b.Count; k++)
{
int index2 = k;
if (a.ElementAt<DataGridViewRow> (index1).Cells[0].Value.ToString() == b.ElementAt<DataGridViewRow>(index2).Cells[0].Value.ToString() && a.ElementAt<DataGridViewRow>(index1).Cells[1].Value.ToString() == b.ElementAt<DataGridViewRow>(index2).Cells[1].Value.ToString())
{
a.RemoveAt(index1);
}
else continue;
}
}
To find the null pointer exception, use the debugger. One of your variables is null.
But once that is fixed, you cannot modify a list while you are iterating over it. The simplest solution in the code you've presented is to change your foreach loops into for loops.
From the MSDN documentation for foreach:
The foreach statement repeats a group of embedded statements for each element in an array or an object collection. The foreach statement is used to iterate through the collection to get the desired information, but should not be used to change the contents of the collection to avoid unpredictable side effects.
You probably have a null Value, so ToString() fails.
A few possibilities:
row.Cells[0] is null
row.Cells[1] is null
row.Cells[0].Value is null
row.Cells[1].Value is null
You cannot delete an element from a collection that you are iterating through. The solution is to store the list of elements to be deleted in another List, and then delete them in another iteration. Following is a solution.
//New list that will contain the Objects to be deleted later on.
List<DataGridView> listToDelete = new List<DataGridView>();
if (a.Count != 0)
{
foreach(DataGridViewRow row in a )
{
foreach (DataGridViewRow newrow in b)
{
if( row.Cells[0].Value.ToString() == newrow.Cells[0].Value.ToString() &&
row.Cells[1].Value.ToString() == newrow.Cells[1].Value.ToString())
{
listToDelete.Add(row);
}
}
}
}
foreach (DataGridView d in listToDelete) {
a.Remove(d);
}

Categories