Is string in array? - c#

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.

Related

if check nesting c sharp [duplicate]

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
}

Array.Exist() only recognizing last element of an array

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

Performing function on each array element, returning results to new array

I'm a complete Linq newbie here, so forgive me for a probably quite simple question.
I want to perform an operation on every element in an array, and return the result of each of these operations to a new array.
For example, say I have an array or numbers and a function ToWords() that converts the numbers to their word equivalents, I want to be able to pass in the numbers array, perform the ToWords() operation on each element, and pass out a string[]
I know it's entirely possible in a slightly more verbose way, but in my Linq adventures I'm wondering if it's doable in a nice one-liner.
You can use Select() to transform one sequence into another one, and ToArray() to create an array from the result:
int[] numbers = { 1, 2, 3 };
string[] strings = numbers.Select(x => ToWords(x)).ToArray();
It's pretty straight forward. Just use the Select method:
var results = array.Select(ToWords).ToArray();
Note that unless you need an array you don't have to call ToArray. Most of the time you can use lazy evaluation on an IEnumerable<string> just as easily.
There are two different approaches - you can use Select extension method or you can use select clause:
var numbers = new List<int>();
var strings1 = from num in numbers select ToWords(num);
var strings2 = numbers.Select(ToWords);
both of them will return IEnumerable<>, which you can cast as you need (for example, with .ToArray() or .ToList()).
You could do something like this :
public static string[] ProcessStrings(int[] intList)
{
return Array.ConvertAll<int, string>(intList, new Converter<int, string>(
delegate(int number)
{
return ToWords();
}));
}
If it is a list then :
public static List<string> ProcessStrings(List<int> intList)
{
return intList.ConvertAll<string>(new Converter<int, string>(
delegate(int number)
{
return ToWords();
}));
}
Straight simple:
string[] wordsArray = array.ToList().ConvertAll(n => ToWords(n)).ToArray();
If you are OK with Lists, rather than arrays, you can skip ToList() and ToArray().
Lists are much more flexible than arrays, I see no reason on earth not to use them, except for specific cases.

How to make your if shorter?

I understood that when using Regex I can enter the value | to search for many values. For example:
Regex sabrina = new Regex("Rihanna|rihanna|Sabrina|sabrina");
I have a string which I want to compare to other values, so I use if like this:
if (rihanna == "Rihanna" || rihanna == "sabrina")
My question is if it possible to make the if shorter? I know this code is not working but what I'm looking for something like this:
if (rihanna == "Rihanna|sabrina")
Single line solution:
if("Rihanna|rihanna|Sabrina|sabrina".Split(new[] {'|'}).Contains(rihanna))
or without String.Split method usage:
if ((new[] { "Rihanna", "rihanna", "Sabrina", "sabrina" }).Contains(rihanna))
If that kind of check is performed more than once you should save string[] array of possible values into a variable:
var names = new[] { "Rihanna", "rihanna", "Sabrina", "sabrina" };
if(names.Contains(rihanna))
You could use a List<string> along with the Enumerable.Contains method.
Example:
var values = new List<string> { "Rihanna", "rihanna", "Sabrina", "sabrina" };
if (values.Contains(rihanna))
{
// etc.
}
The if statement is now a lot more concise, and you can add more items to your list quickly and easily. If you're performing this operation frequently, you should move the declaration of the list to a member variable in the containing class so that you don't incur the overhead of list initialization every time this method is called.
An even better solution would be to use Enumerable.Any and String.Equals to perform a case-insensitive comparison:
if (values.Any(x => String.Equals(rihanna, x, StringComparison.OrdinalIgnoreCase))
{
// your code here
}
Although the if statement is now longer, the solution is much more robust.
If you're looking for easier maintenance of a potentially long list of string candidates, why not use a switch statement? Technically it will be "longer" character-wise, but if you have to modify things down the road, or provide some subtle secondary processing, it could make things a lot easier.
As an alternative to the above answers, perhaps you could consider using an extension method:
public static bool EqualsAny(this string input, params string[] values)
{
return values.Any(v => String.Equals(input, v, StringComparison.OrdinalIgnoreCase));
}
With usage like:
if (rihanna.EqualsAny("Rihanna", "Sabrina"))
This should give pretty readable/compact/short if comparisons for you, especially in comparison to some of the other alternatives here.
Tweak the EqualsAny check if you want to have the OrdinalIgnoreCase or not or feel free to add any overloads you wish. Could even implement the whole piping/splitting where you'd pass in "Rihanna|Sabrina".
EDIT: Perhaps more critically, it centralizes how you compare rather than duplicating the code everywhere.
You can use your own Regex and use it as a single line..
if (Regex.Match(rihanna, "Rihanna|rihanna|Sabrina|sabrina").Success)
Or make it case-insensative like this..
if (Regex.Match(rihanna, "rihanna|sabrina", RegexOptions.IgnoreCase).Success){
Ignore casing, which looks like something you're going for, and use String.Compare:
if(String.Compare(rihanna, "sabrina", StringComparison.OrdinalIgnoreCase) == 0 ||
String.Compare(rihanna, "rihana", StringComparison.OrdinalIgnoreCase) == 0 ) {
// do stuff
}
Dictionary or HashSet (potentially with case insensitive check on names) is another approach which will give you better performance if you have more than several items and repeat checks often.
var listToCheck = new Dictionary<string, string>(
StringComparer.CurrentCultureIgnoreCase) { { "rihanna", null}};
if (listToCheck.ContainsKey("Rihanna")) ....

Most Efficient to pass a collection of Char to method for population

Is this the best way to get a collection of chars? Wondering is it overkill to use List for primitives such as char?
private void GetChars(ref List<char> charsToPopulate)
{
foreach(Thing t in Things)
{
charsToPopulate.Add(t.CharSymbol);
}
}
Using a lazy sequence will allow you a large amount of flexibility with how you can work with the characters. You really should refactor the method to something like this.
private IEnumerable<char> GetChars(IEnumerable<Thing> things)
{
return things.Select(thing => thing.CharSymbol);
}
This way they can wrap it into any collection they want:
var list = GetChars(Things).ToList();
var array = GetChars(Things).ToArray();
Or remove the method all together:
var chars = Things.Select(thing => thing.CharSymbol).ToList();
The most efficient way is to receive a preallocated array of chars, to which you'd write elements. Of course, this requires the size to be known in advance.
Second most efficient would be allocating the array within the method, and then filling it. This still requires some ability to quickly compute the size of Things, but at least hides it from the caller.
If there's no way to find out the size in advance (e.g. Things is a deferred sequence that is large enough that caching it is unfeasible), then your solution is likely to be as good as it gets.
You'll want to pass the reference to the list by value, not by reference:
private void GetChars(List<char> charsToPopulate)
Apart from that, your code is fine. Using lists for primitive types such as char is very common.
If you're interested in writing the same implementation slightly different, you could use LINQ to populate the list from the things:
{
charsToPopulate.AddRange(from t in things select t.CharSymbol);
}
BTW, there is nothing wrong with creating the list within the method. You don't need to 'allocate' the list before passing it to the method:
private List<char> GetChars()
{
List<char> charsToPopulate = new List<char>();
foreach(Thing t in Things)
{
charsToPopulate.Add(t.CharSymbol);
}
return charsToPopulate;
}
or using LINQ:
private List<char> GetChars()
{
return things.Select(t => t.CharSymbol)
.ToList();
}

Categories