C# LastIndexOf not giving correct result - c#

in this particular line of code :
correct = Array.LastIndexOf(turns.ToArray(), false, 4, 0);
I get result correct = -1, well how is this even possible ?
turns[0] up to turns[3] are equal to false turns[4]=true and turns[5]=false is it possible to be caused because the last index i want to be looked up to is 4 and it has value different than the required one ?

The issue is with the last argument (count). This restricts the number of elements searched. You are restricting it to search 0 elements starting at index 4. Thus, it doesn't find anything.

Your count indicates searching 0 elements in the section.
correct = Array.LastIndexOf(turns.ToArray(), false, 4, 2);

Try this out:
correct = Array.LastIndexOf(turns.ToArray(), false, turns.Length, turns.Length);
What were you doing wrong:
never hard code array length (especially in your case, when the array is filled with values)
the first index is actually the starting search index from backwards, and the second index is actually the count, i.e. how many items to search (MSDN constructor clarification)
Update 1:
Made a mistake on the starting index and the count number. Updated the changes, thank you #Steve for pointing it out.

Related

An unexpected behavior of LastIndexOf()?

While using LastIndexOf to search for a short string in a longer string I came across behavior that I find somewhat counterintuitive:
If I have a haystack and a needle:
var h = "abcabcabc";
var n = "abc";
And I tell LastIndexOf to start searching at index 3, 4, I would expect it to start looking there and proceed towards the start of the string, and hence return 3:
012345678
abcabcabc
abc <- try index 4, no
abc <- found at index 3
..but it actually locates the first abc and returns 0. It behaves like there is an assumption "user wants to start searching for a string of length 3 starting at index 4; the string couldn't possibly occur at any index higher than 2 so search will begin from index 2.. found at index 0" - while that would be true if one was starting from the very end of the string i.e. a needle of length 3 couldn't possibly be found any later than haystack.Length-3, I don't find it logical to adopt the approach in the middle of a string
Another way of looking at it is "the haystack is substringed so that it has a length equal to the startIndex and then the substringed haystack is searched" - but again, I don't find it reasonable to chop a document and remove a potential match
While I can reason the search logic out thus and try to remember it, it seems illogical to me to operate in such a manner, so I'm here asking if there is some underlying reason for this behavior that will make it easier to reason about?
Note: it's also fine to say "no, your logic of "start at 4, find at 3 is unreasonable because.." - it would help adjust my mental model of how I think LastIndexOf should work
from the documentation - it says
Reports the zero-based index position of the last occurrence of a
specified string within this instance. The search starts at a
specified character position and proceeds backward toward the
beginning of the string.
So it searches from the value to the beginning of the string. Different starting point as your expectation.
Update: as Matthew Watson mentioned in his comment from the source code
For LastIndexOf specifially, overloads which take a 'startIndex' and 'count' behave differently than their IndexOf counterparts. 'startIndex' is the index of the last char element that should be considered when performing the search. For example, if startIndex = 4, then the caller is indicating "when finding the match I want you to include the char element at index 4, but not any char elements past that point.
var h = "abcabcabc";
//index 012345678
// ^ last element that will be considdered "abca"
var n = "abc";
int result = h.LastIndexOf(n,3); //0

Multi-dimensional array access with negative index

Ok, maybe I'm dumb, but Why there is no exception being thrown in the following code?
It's clear that the index by which the _cells array is being accessed is negative (posCol + col = -1) as shown in the picture.
Thanks in advance.
Most likely shape[row,col] is equal to 0. If it is, C# will short circuit the rest of the conditional since it can already determine the entire thing will evaluate to false. Since it never evaluates the second one with the negative index, it doesn't matter that posCol is negative.

Enum.GetNames() results in unexpected order with negative enum constants

I have the following enum definition (in C#):
public enum ELogLevel
{
General = -1, // Should only be used in drop-down box in Merlinia Administrator log settings
All = 0, // Should not be used as a level, only as a threshold, effectively same as Trace
Trace = 1,
Debug = 2,
Info = 3,
Warn = 4,
Error = 5,
Fatal = 6,
Off = 7 // Should not be used as a level, only as a threshold
}
Now, when I do an Enum.GetNames() on this type I get a string array with 9 elements as expected, but the order is All, Trace, ... , Off, General, which is not what I was expecting.
Here's the MSDN documentation for Enum.GetNames():
"Remarks: The elements of the return value array are sorted by the
values of the enumerated constants."
What's going on here? I can change my program to take this "functionality" into account, but I'd kind of like to know why .NET is doing what it's doing.
This is a known bug with both GetNames() and GetValues() that was reported here, but ended up getting closed as won't fix:
Yes, this method indeed has a bug where it returns the array of enum values sorted as unsigned-types (-2 is 0xFFFFFFFE and -1 is 0xFFFFFFFF in two's complement, that's why they are showing up at the end of the list) instead of returning values sorted by their signed-types.
Unfortunately, we cannot change the sort order of GetValues because we will break all existing .NET programs that have been written to depend on the current sorting behavior [...]
Looks like you'll have to reorder the values yourself.
Depending on how the sorting occurs, it may be that it is sorting the values as if they were unsigned, in which case, -1 = 0xffffffff, which is of course greater than 7.

IndexOf method returns 0 when it should had return -1 in C# / Java

A friend of mine came to me with this strange behavior which i can't explain, any insight view would be appreciated.
Im running VS 2005 (C# 2.0), the following code show the behavior
int rr = "test".IndexOf("");
Console.WriteLine(rr.ToString());
the above code, print "0" which clearly show it should have return -1
This also happen in Java where the following Class show the behavior:
public class Test{
public static void main(String[] args){
System.out.println("Result->"+("test".indexOf("")));
}
}
Im running Java 1.6.0_17
Quote from the C# documentation:
If value is Empty, the return value
is 0.
The behavior that you describe is entirely as expected (at least in C#).
0 is correct. Start at position zero and you can (trivially) match a zero-length string. Likewise, "" contains "".
This is not an exception to the rule, but rather a natural consequence of how indexOf and startsWith are defined.
You’re claiming that "test".indexOf("") should return -1. This is essentially equivalent to the claim that "test".startsWith("") should return false. Why is this? Although this case is specifically addressed in the documentation as returning true, this is not just an arbitrary decision.
How would you decide "test".startsWith("te"), for example? The simplest way is to use recursion. Since both strings start with the character 't', you call "est".startsWith("e") and return the result. Similarly, you will call "st".startsWith("") and return the result. But you already know that the answer should be true, so that is why every string starts with "".
0 is correct. The Javadocs point out that indexOf works as follows:
The integer returned is the smallest
value k such that:
this.startsWith(str, k)
Any string starting with "" is equal to the original string (and every string starts with ""), so the smallest k for str = "" is always 0.
Think of it this way: IndexOf, when looking for a string, will start at position 0, try to match the string, if it doesn't fit, move on to position 1, 2, etc. When you call it with an empty string, it attempts to match the empty string with the string starting at position 0 with length 0. And hooray, nothing equals nothing.
Side note: There's no real reason to use ToString when you're using Console.Write/WriteLine. The function automatically calls the ToString method of the object in question. (Unless overloading ToString)
It should return 0. You are looking for the first occurrence of an empty string, right? :)
More fun php actually does a way better job!
php -r "print strpos('test','');"
PHP Warning: strpos(): Empty delimiter. in Command line code on line 1
Just for the fun of it. It also works like that in python
>>> "test".startswith("")
True
>>> "test".index("")
0
Python throws a ValueError instead of the -1 that is nice.
>>> "test".index('r')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found

Need help understanding code

I am taking a C# class and I need help understanding the following code.
The code has an array which represents responses to a survey, with values 1 thru 10.
The output displays these ratings and the frequency of how many times a value was selected.
The following code is from my book, but I have modified it to just a basic example.
int[] responses = { 3, 2, 5, 6, 3, 5 , 4, 5, 5, 5};
int[] frequency = new int[7];
for (int answer = 0; answer < responses.Length; answer++)
++frequency[responses[answer]];
for (int rating = 1; rating < frequency.Length; rating++)
Console.WriteLine(rating + ", " + frequency[rating]);
Console.Read();
How does the line ++frequency[responses[answer]]; work? In looking at this, if I take reponses[answer] the first time through the loop, this would represent responses[0] which would be a 3, correct? This is where I get confused, what does the ++frequency part of this line do?
frequency[responses[answer]] = frequency[responses[answer]] + 1;
EDIT: I think it's pretty unclear to write it like that. As a personal preference, I don't like using unary operations (++x, x++, etc) on elements that have lots of indexes present.
It adds one to the frequency at that location in the array.
For example, the frequency at position 3 (from your example) will be increased by one after that line executes.
EDIT: So, in more detail, when answer = 0, responses[0] = 3, so frequency[3] gets one added to it.
The ++ could very easily be at the end of the command as well. In other words,
++frequency[responses[answer]];
is the same thing (IN THIS CASE) as using
frequency[responses[answer]]++;
Let's break it down: As you point out, on the first pass responses[answer] will evaluate to "3"
So this then looks like ++frequency[3]
The ++ is incrementing the value of the array at index 3 by 1
Simple enough?
I should also point out that applying the ++ before the array rather than after it does effect how the incrementing is executed (although it doesn't effect the results of this code).
For instance:
int n = 2;
int j = ++n;
int k = n++;
What are j and k?
j will be 3, and k will also be 3. This is because if you place the ++ before, it evaluates it first. If you place it at the end, it evaluates it after the rest of the expression.
If it helps, think of ++frequency[] as "frequency = frequency + 1".
If the ++ operator comes before the variable, then the increment is applied before the statement is executed. If the ++ comes afterwards, then the statement is executed and then the variable is incremented.
In this case, it doesn't matter, since incrementing before or after doesn't impact the logic.
Since "responses[answer]" evaluates to a number, that line of code is incrementing the frequency entry at that array index. So the first time through, answer is 0, so responses[answer] is 3, so the frequency[3] box is getting incremented by 1. The next time through, the frequency[2] box is incremented... etc. etc. etc.
frequency is an array, where all elements are initialized to 0 (the default value for an int). The line ++frequency[responses[answer]] will increment the frequency element pointed out by the integer found at responses[answer]. By putting the ++ in front of frequency, the array element will be incremented before the resulting value is returned.
You can read more about the ++ operator here.
In cases like this it's often useful to rewrite the code as you walk it.
When answer = 0
++frequency[responses[0]]
++frequency[3] since responses[0] = 3
frequency now looks like { 0, 0, 0, 1, 0, 0, 0 }
When answer = 1
++frequency[responses[1]]
++frequency[2] since responses[1] = 2
frequency now looks like { 0, 0, 1, 1, 0, 0, 0 }
And so on.
It means increment the value at frequency[ 3 ]. Where 3 is the return result from responses[answer]. Similarly the next iteration would increment the value at frequency[ 2 ].
The ++ operator in C# when applied to an integer will increment it by one.
The specific line you're looking at, frequency is an array of integers with 7 elements. Which is sort of confusing, because the way you explained it in your code, it would appear that this code would break with any value in the responses array above 6.
That issue aside, basically it's incrementing whichever index of the array it's accessing. So in your example responses[0] would be 3. So this line would find the value of frequency[3] and increment it by 1. Since integer arrays are initialized with all values at zero, then after the first iteration, frequency[3] would be 1. Then if there was another 3 later in your responses array, frequency[3] would be incremented again (i.e. responses[4]).
I hope this helps you.
The goal of the code snippet seems to be to determine the number of times each response appears in the 'responses' array. So, for your example set, frequency[3] should be 5, frequency[5] should be 5, etc.
So, the line you are asking about takes the current element from the responses array, and increments the associated value in the frequency array by 1, to indicate that the particular value has been observed in responses.
Once the entire code snippet executes, the frequency array contains the number of times each element from 0 to 7 was observed in the responses array.
It is using the frequency array to count how many times each response was entered. You could have a counter for each answer:
int numberOfOnes = 0;
int numberOfTwos = 0;
// Etc...
But that would be ugly programming and not as easy or efficient. Using the frequency array allows you do not use an if/else if block or a switch and makes your code easier to read.
Another thing about that frequency array.
int[] frequency = new int[7];
This initializes all the integers in the array to 0, that's why you can just start off by incrementing it instead of seeing if it was the first time for that specific response and then initializing it with 1 or something of that nature.
Good luck with all the fun C# you have ahead of you.

Categories