I apologize if this is an obvious answer, but I couldn't find anything related to this behavior on StackOverflow nor on Google. I'm self-teaching c# and am writing a program that involves the use of username/password pairs. In this case, I am using .Exist() to determine if a username is already in my array of usernames.
static bool LookUpS(string targ, string[] arr)
{
if (Array.Exists(arr, e => e == targ))
{
return true;
}
else
{
return false;
}
}
The argument targ comes from the user, and the argument arr is written into the program to specify which array should be searched (this is so that I can use LookUpS on different arrays). The array that I'm testing right now is derived from a text document. I've tested to confirm that the transition from .txt to array is working properly.
Now to the actual issue. I've filled the text document in question with a few values: "Jupiter", "Neptune", "Saturn", "Mars". If I pass any of the first three into LookUpS, it returns false despite the fact that they do exist. The part I don't understand, however, is that if I pass "Mars" (or whatever the last value happens to be) into the function, it returns true like it should. If I were to remove the "Mars" value, LookUpS would say that "Saturn" is true but not the others. Can anyone offer some explanation for this? I can post a more complete picture of the program if that would help in identifying the problem.
In the comments you mention that you split the lines with \n as split separator. But on Windows \r\n is used. Hence your split string array will contain
xxxx\r
yyyy\r
lastUser
The last line does not contain a newline which will work.
That explains why your search in the array finds only the last user in your array. Pass to the split operation not \r but Environment.NewLine.ToCharArray() to remove all newline characters in string array.
Arrays have a built-in method called contains() which should do exactly what you want...
string[] array = { "Jupiter", "Neptune", "Saturn", "Mars" };
if (array.Contains("Neptune")) {
return true;
}
You could simplify it to something like this.
You can use Exists() instead of Any() if you like.
static bool LookUpS(string targ, string[] arr)
{
return (arr.Any(s => s == targ))
}
Or if you want it to be non case-sensitive:
static bool LookUpS(string targ, string[] arr)
{
return (arr.Any(e => String.Equals(e, targ, StringComparison.CurrentCultureIgnoreCase));
}
Or, as Karl suggests, you can use Contains()
static bool LookUpS(string targ, string[] arr)
{
return (arr.Contains(targ);
}
Sometimes simplifying your code can solve some problems :)
The reason that you don't need to use an if .. else to return true or false, is that the methods Any(), Exists() and Contains() return are bool, so you can just return the method call as shown in the examples
Related
Any easier way to write this if statement?
if (value==1 || value==2)
For example... in SQL you can say where value in (1,2) instead of where value=1 or value=2.
I'm looking for something that would work with any basic type... string, int, etc.
How about:
if (new[] {1, 2}.Contains(value))
It's a hack though :)
Or if you don't mind creating your own extension method, you can create the following:
public static bool In<T>(this T obj, params T[] args)
{
return args.Contains(obj);
}
And you can use it like this:
if (1.In(1, 2))
:)
A more complicated way :) that emulates SQL's 'IN':
public static class Ext {
public static bool In<T>(this T t,params T[] values){
foreach (T value in values) {
if (t.Equals(value)) {
return true;
}
}
return false;
}
}
if (value.In(1,2)) {
// ...
}
But go for the standard way, it's more readable.
EDIT: a better solution, according to #Kobi's suggestion:
public static class Ext {
public static bool In<T>(this T t,params T[] values){
return values.Contains(t);
}
}
C# 9 supports this directly:
if (value is 1 or 2)
however, in many cases: switch might be clearer (especially with more recent switch syntax enhancements). You can see this here, with the if (value is 1 or 2) getting compiled identically to if (value == 1 || value == 2).
Is this what you are looking for ?
if (new int[] { 1, 2, 3, 4, 5 }.Contains(value))
If you have a List, you can use .Contains(yourObject), if you're just looking for it existing (like a where). Otherwise look at Linq .Any() extension method.
Using Linq,
if(new int[] {1, 2}.Contains(value))
But I'd have to think that your original if is faster.
Alternatively, and this would give you more flexibility if testing for values other than 1 or 2 in future, is to use a switch statement
switch(value)
{
case 1:
case 2:
return true;
default:
return false
}
If you search a value in a fixed list of values many times in a long list, HashSet<T> should be used. If the list is very short (< ~20 items), List could have better performance, based on this test
HashSet vs. List performance
HashSet<int> nums = new HashSet<int> { 1, 2, 3, 4, 5 };
// ....
if (nums.Contains(value))
Generally, no.
Yes, there are cases where the list is in an Array or List, but that's not the general case.
An extensionmethod like this would do it...
public static bool In<T>(this T item, params T[] items)
{
return items.Contains(item);
}
Use it like this:
Console.WriteLine(1.In(1,2,3));
Console.WriteLine("a".In("a", "b"));
You can use the switch statement with pattern matching (another version of jules's answer):
if (value switch{1 or 3 => true,_ => false}){
// do something
}
Easier is subjective, but maybe the switch statement would be easier? You don't have to repeat the variable, so more values can fit on the line, and a line with many comparisons is more legible than the counterpart using the if statement.
In vb.net or C# I would expect that the fastest general approach to compare a variable against any reasonable number of separately-named objects (as opposed to e.g. all the things in a collection) will be to simply compare each object against the comparand much as you have done. It is certainly possible to create an instance of a collection and see if it contains the object, and doing so may be more expressive than comparing the object against all items individually, but unless one uses a construct which the compiler can explicitly recognize, such code will almost certainly be much slower than simply doing the individual comparisons. I wouldn't worry about speed if the code will by its nature run at most a few hundred times per second, but I'd be wary of the code being repurposed to something that's run much more often than originally intended.
An alternative approach, if a variable is something like an enumeration type, is to choose power-of-two enumeration values to permit the use of bitmasks. If the enumeration type has 32 or fewer valid values (e.g. starting Harry=1, Ron=2, Hermione=4, Ginny=8, Neville=16) one could store them in an integer and check for multiple bits at once in a single operation ((if ((thisOne & (Harry | Ron | Neville | Beatrix)) != 0) /* Do something */. This will allow for fast code, but is limited to enumerations with a small number of values.
A somewhat more powerful approach, but one which must be used with care, is to use some bits of the value to indicate attributes of something, while other bits identify the item. For example, bit 30 could indicate that a character is male, bit 29 could indicate friend-of-Harry, etc. while the lower bits distinguish between characters. This approach would allow for adding characters who may or may not be friend-of-Harry, without requiring the code that checks for friend-of-Harry to change. One caveat with doing this is that one must distinguish between enumeration constants that are used to SET an enumeration value, and those used to TEST it. For example, to set a variable to indicate Harry, one might want to set it to 0x60000001, but to see if a variable IS Harry, one should bit-test it with 0x00000001.
One more approach, which may be useful if the total number of possible values is moderate (e.g. 16-16,000 or so) is to have an array of flags associated with each value. One could then code something like "if (((characterAttributes[theCharacter] & chracterAttribute.Male) != 0)". This approach will work best when the number of characters is fairly small. If array is too large, cache misses may slow down the code to the point that testing against a small number of characters individually would be faster.
Using Extension Methods:
public static class ObjectExtension
{
public static bool In(this object obj, params object[] objects)
{
if (objects == null || obj == null)
return false;
object found = objects.FirstOrDefault(o => o.GetType().Equals(obj.GetType()) && o.Equals(obj));
return (found != null);
}
}
Now you can do this:
string role= "Admin";
if (role.In("Admin", "Director"))
{
...
}
public static bool EqualsAny<T>(IEquatable<T> value, params T[] possibleMatches) {
foreach (T t in possibleMatches) {
if (value.Equals(t))
return true;
}
return false;
}
public static bool EqualsAny<T>(IEquatable<T> value, IEnumerable<T> possibleMatches) {
foreach (T t in possibleMatches) {
if (value.Equals(t))
return true;
}
return false;
}
I had the same problem but solved it with a switch statement
switch(a value you are switching on)
{
case 1:
the code you want to happen;
case 2:
the code you want to happen;
default:
return a value
}
I am aware this question as been asked. And I am not really looking for a function to do so. I was hoping to get some tips on making a little method I made better. Basically, take a long string, and search for a smaller string inside of it. I am aware that there is literally always a million ways to do things better, and that is what brought me here.
Please take a look at the code snippet, and let me know what you think. No, its not very complex, yes it does work for my needs, but I am more interested in learning where the pain points would be using this for something I would assume it would work for, but would not for such and such reason. I hope that makes sense. But to give this question a way to be answered for SO, is this a strong way to perform this task (I somewhat know the answer :) )
Super interested in constructive criticism, not just in "that's bad". I implore you do elaborate on such a thought so I can get the most out of the responses.
public static Boolean FindTextInString(string strTextToSearch, string strTextToLookFor)
{
//put the string to search into lower case
string strTextToSearchLower = strTextToSearch.ToLower();
//put the text to look for to lower case
string strTextToLookForLower = strTextToLookFor.ToLower();
//get the length of both of the strings
int intTextToLookForLength = strTextToLookForLower.Length;
int intTextToSearch = strTextToSearchLower.Length;
//loop through the division amount so we can check each part of the search text
for(int i = 0; i < intTextToSearch; i++)
{
//substring at multiple positions and see if it can be found
if (strTextToSearchLower.Substring(i,intTextToLookForLength) == strTextToLookForLower)
{
//return true if we found a matching string within the search in text
return true;
}
}
//otherwise we will return false
return false;
}
If you only care about finding a substring inside a string, just use String.Contains()
Example:
string string_to_search = "the cat jumped onto the table";
string string_to_find = "jumped onto";
return string_to_search.ToLower().Contains(string_to_find.ToLower());
You can reuse VB's Like operator this way:
1) Make a reference to Microsoft.VisualBasic.dll library.
2) Use the following code.
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
if (LikeOperator.LikeString(Source: "11", Pattern: "11*", CompareOption: CompareMethod.Text)
{
// Your code here...
}
To implement your function in a case-insensitive way, it may be more appropriate to use IndexOf instead of the combination of two ToLower() calls with Contains. This is both because ToLower() will generate a new string, and because of the Turkish İ Problem.
Something like the following should do the trick, where it returns False if either term is null, otherwise uses a case-insensitive IndexOf call to determine if the search term exists in the source string:
public static bool SourceContainsSearch(string source, string search)
{
return search != null &&
source?.IndexOf(search, StringComparison.OrdinalIgnoreCase) > -1;
}
I want to compare two integer arrays and then print the equals out. I tried the Intersect method:
var checkingDuplicates = boughttickets.Intersect(winningtickets).Any();
and then used a if-statement:
if (checkingDuplicates == false)
{
Console.WriteLine("Sorry, You didn't win anything");
}
else
{
Console.WriteLine(checkingDuplicates);
}
However, the output always returns true with this if-statement.
I am truly sorry if i have some Spelling misstakes, my native language is not English.
Any takes a sequence of items and returns a boolean indicating if there are any items in that sequence.
You don't want to know if there are any items in that sequence, you just want to know what all of the items in that sequence are. That means don't call Any, and you'll have your sequence of the intersection of those two arrays.
First i would say read the documentation. From your comment above, you can not call .toString() on IEnumerable withou defining .tostring implementation.
Try this
var checkingDuplicates = boughttickets.Intersect(winningtickets);
if (!checkingDuplicates.Any())
{
Console.WriteLine("Sorry, You didn't win anything");
}
else
{
foreach(TICKET checkingDuplicate in checkingDuplicates)
{
Console.WriteLine("FETCH AND PRINT YOUR TICKET INFORMATION FROM TICKET OBJECT/CLASS");
}
}
In the foreach loop above TICKET is the type of object you are using on the IEnumerable lists above.
I have a program that needs to compare any given string with a predefined string and determine if an insertion error, deletion error, transposition or substitution error was made.
For example, if the word dog was presented to the user and the user submits dogs or doge, it should notify the user that an insertion error has been made.
How do I go about this?
You probably need to write a method for each of the individual error types to see if it's an error, like:
bool IsInsertionError(string expected, string actual) {
// Maybe look at all of the chars in expected, to see if all of them
// are there in actual, in the correct order, but there's an additional one
}
bool IsDeletionError(string expected, string actual) {
// Do the reverse of IsInsertionError - see if all the letters
// of actual are in expected, in the correct order,
// but there's an additional one
}
bool IsTransposition(string expected, string actual) {
// This one might be a little tricker - maybe loop through all the chars,
// and if expected[i] != actual[i], check to see if
// expected[i+1] = actual[i] and actual[i-1]=expected[i]
// or something like that
}
Once you build out all the individual rules, and you first check for regular equality, fire each of them off one at a time.
You've got to just break problems like this down into small components, then once you have a bunch of easy problems, solve them one at a time.
Off the top of my head but I think this should get you started:
Insertion and Deletion should be pretty simple; just check the lengths of the strings.
if(originalString.Length > newString.Length)
{
//deletion
}
else if(originalString.Length < newString.Length)
{
//insertion
}
To detect transposition, check if the lengths match and if so, you could create two List<char> from the two strings. Then check if they match using the expression below
bool isTransposed = originalList.OrderBy(x => x).SequenceEquals(newList.OrderBy(y => y));
To detect substitution, you could use the Hamming Distance and check if it's greater than 0.
I would suggest you to create a function which will take a parameter as the input sting. The function would look more or less like this. Use the function wherever you want then.
private void CheckString(string userString)
{
string predefinedString = "dog";
if (userString == predefinedString)
{
// write your logic here
}
else
{
MessageBox.Show("Incorrect word"); // notify the users about incorrect word over here
}
}
What would be the best way to look in a string[] to see if it contains a element. This was my first shot at it. But perhaps there is something that I am overlooking. The array size will be no larger than 200 elements.
bool isStringInArray(string[] strArray, string key)
{
for (int i = 0; i <= strArray.Length - 1; i++)
if (strArray[i] == key)
return true;
return false;
}
Just use the already built-in Contains() method:
using System.Linq;
//...
string[] array = { "foo", "bar" };
if (array.Contains("foo")) {
//...
}
I know this is old, but I wanted the new readers to know that there is a new method to do this using generics and extension methods.
You can read my blog post to see more information about how to do this, but the main idea is this:
By adding this extension method to your code:
public static bool IsIn<T>(this T source, params T[] values)
{
return values.Contains(source);
}
you can perform your search like this:
string myStr = "str3";
bool found = myStr.IsIn("str1", "str2", "str3", "str4");
It works on any type (as long as you create a good equals method). Any value type for sure.
You're simply after the Array.Exists function (or the Contains extension method if you're using .NET 3.5, which is slightly more convenient).
Linq (for s&g's):
var test = "This is the string I'm looking for";
var found = strArray.Any(x=>x == test);
or, depending on requirements
var found = strArray.Any(
x=>x.Equals(test, StringComparison.OrdinalIgnoreCase));
Is the array sorted? If so you could do a binary search. Here is the .NET implementation as well. If the array is sorted then a binary search will improve performance over any iterative solution.
Arrays are, in general, a poor data structure to use if you want to ask if a particular object is in the collection or not.
If you'll be running this search frequently, it might be worth it to use a Dictionary<string, something> rather than an array. Lookups in a Dictionary are O(1) (constant-time), while searching through the array is O(N) (takes time proportional to the length of the array).
Even if the array is only 200 items at most, if you do a lot of these searches, the Dictionary will likely be faster.
As mentioned many times in the thread above, it's dependent on the framework in use.
.Net Framework 3 and above has the .Contains() or Exists() methods for arrays. For other frameworks below, can do the following trick instead of looping through array...
((IList<string>)"Your String Array Here").Contains("Your Search String Here")
Not too sure on efficiency...
Dave
You can also use LINQ to iterate over the array. or you can use the Find method which takes a delegate to search for it. However I think the find method is a bit more expensive then just looping through.
This is quicker than iterating through the array manually:
static bool isStringInArray(string[] strArray, string key)
{
if (strArray.Contains(key))
return true;
return false;
}
If you don't want to or simply can't use Linq you can also use the static Array.Exists(...); function:
https://msdn.microsoft.com/en-us/library/yw84x8be%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
var arr = new string[]{"bird","foo","cat","dog"};
var catInside = Array.Exists(
arr, // your Array
(s)=>{ return s == "cat"; } // the Predicate
);
When the Predicate do return true once catInside will be true as well.