Runtime: Proposal: Array.SearchFor method

Created on 16 Jun 2018  路  10Comments  路  Source: dotnet/runtime

Array.Find Method is not practical, because it returns the default value of T if the search failed, i.e if T is int, it returns zero when it found nothing!.. This forces us to to use the Array.Exists first to make sure the element exists before reading it, which means we have to do the search twice!

if (Array.Exists(new[] { 1, 2, 3 }, (N) => N < 0))
    Console.WriteLine(Array.Find(new[] {1, 2, 3}, (N) => N < 0));

I suggest to add this method to solve this issue:

public static (bool Exists, T Item) SearchFor<T>(
    T[] array, Predicate<T> match)
{
    foreach (T item in array)
        if (match(item))
            return (true, item);

    return (false, default(T));
}

so we can use it like this:

var result = Array.SearchFor(new[] { 1, 2, 3 }, (N) => N < 0);
if (result.Exists)
    Console.WriteLine(result.Item);

And you can mark Array.Find method as obsolete.

Note:
It will be better if the implementaion of SearchFor can use parallelism to be faster.

area-System.Collections question

Most helpful comment

It is slightly slower to get the index then using it to traverse the Array again!

Indexing into an array does not require traversing it.

It has no purpose

Not true. It's why methods like LINQ's FirstOrDefault exist. Just because you don't currently have a need for it doesn't mean it shouldn't exist.

search methods should return a tuple containing both the inexed and the value.

If you prefer that style, you can add your own extension method that you use in all your projects, publish on NuGet for others to use, etc.

All 10 comments

https://msdn.microsoft.com/en-us/library/d9hy2xwa(v=vs.110).aspx

This method is already on Array, your example is incorrect...

It would perhaps be useful to have offset and count parameters on that method to avoid having to drop down to your own logic for such.

@juliusfriedman
Sorry, I can't clearly get what you mean!
I know that Array.Find exists and this issue is about it.. The Docs you refered to says:

Return Value
Type: T
The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type T.

This is not efficient as I explained.

your example is incorrect

What example exactly and how?

You can use FindIndex instead - it will return -1 if not found.

@MohammadHamdyGhanem, my apolagies, your actually correct my mistake... I read that wrong while looking at other methods...

Definitely agree that there should be a variation which indicates success unambiguously.. e.g. TryFind rather than SearchFor, good call none the less and sorry for the confusion.

@karelz
Thanks. There are many ways to do it, such as:

var result = (from int N in new[] { 1, -2, 3 }
                where N < 0
                select N).AsParallel();

if (result.Count() > 0)
    Console.WriteLine(result.ElementAt(0));

But I wanted to point out that there is a problem with the Find Method, that can be solved with Tuples. I once asked to review all the framework for such legacy methods, and you asked me to point out them. This is one of them that can be improved with new C# syntax.
Thanks.

@juliusfriedman
That's OK.
I don't mind using any suitable name for the new method. I just gave an example. TryFind is OK.
Thanks.

I don't think we should add "overloads" (requires new method name) with tuples, when there is fairly straightforward existing solution - look for index via "overload" FindIndex instead of for value.
It there was not FindIndex, I would be fine adding SearchFor.

@karelz
At leat mark Find method obsolete. It has no purpose and error prone

@karelz
Besides:
It is slightly slower to get the index then using it to traverse the Array again!
I think tuples should take over, and search methods should return a tuple containing both the inexed and the value.

It is slightly slower to get the index then using it to traverse the Array again!

Indexing into an array does not require traversing it.

It has no purpose

Not true. It's why methods like LINQ's FirstOrDefault exist. Just because you don't currently have a need for it doesn't mean it shouldn't exist.

search methods should return a tuple containing both the inexed and the value.

If you prefer that style, you can add your own extension method that you use in all your projects, publish on NuGet for others to use, etc.

Was this page helpful?
0 / 5 - 0 ratings