Skip to content
This repository has been archived by the owner on Nov 19, 2020. It is now read-only.

IndexOutOfRangeException exception in Matrix class, .First method when using lambda #696

Closed
bebenins opened this issue Jul 10, 2017 · 4 comments

Comments

@bebenins
Copy link

bebenins commented Jul 10, 2017

Hello,
I think this should be gracefully handled in .First method.
Here's what I have...

I need to find an index of a specific Point.X in an array of Points. So I use this expression:

    double myX = 700;
    int index = fft.First(p => p.X >= myX);

It works just fine if myX isn't grater than the maximum Point.X in fft array. But if my fft array Point.X is less than myX, I get an exception:

System.IndexOutOfRangeException occurred
HResult=-2146233080
Message=Index was outside the bounds of the array.
Source=Accord.Math
StackTrace:
at Accord.Math.Matrix.First[T](T[] data, Func`2 func)
InnerException:

What is the easiest/elegant "patch" I can do for now?
Thank you!

Edit: Just in case, this is using Accord.Math 3.4.0.0

@cesarsouza
Copy link
Member

cesarsouza commented Jul 10, 2017

Hi @bebenins,

In this case, the exception happens because the point could not be found right?

I would like to avoid returning -1 in this case because -1 can be interpreted as a correct index if you use it with the .Get() and .Set() functions (where it would mean "return the last element in the array").

I guess it would be better to add a FirstOrDefault method that could handle this case, where the output could be an index, or null. But it might take a while until it could be added into a release (or even pre-release version, since the last one was published yesterday).

If you want a quick (but not elegant) fix for now, you can add an extension method like this to your project:

public static int? FirstOrDefault<T>(this T[] array, Func<T, bool> pred)
{
    try 
    {
        return array.First(array, pred);
    }
    catch (IndexOutOfRangeException ex)
    {
    }

    return null;
}

Then call it instead of .First().

PS: I have just typed the code above here in GitHub and didn't attempt to compile, so it might contain errors.

Regards,
Cesar

@bebenins
Copy link
Author

Thanks Cesar!
Yes I'm fairly certain the reason for exception is because value cannot be found. I agree that -1 isn't ideal and FirstOrDefault support would be awesome.
Thanks for the suggestion in the mean time!

@cesarsouza
Copy link
Member

cesarsouza commented Jul 10, 2017

Alternatively, you can also use

double myX = 700;
int[] indices = fft.First(p => p.X >= myX, firstOnly: true);

And then check if the length of the indices vector is zero before you try to get its first element. If the length is zero, it means the item was not found; otherwise, this vector will contain exactly one value which is the first index where the element has been found.

I guess this is the easiest and most elegant workaround you would have right now.

@cesarsouza
Copy link
Member

Fixed in 3.7.0. You can now use the .FirstOrNull() method to find the first value in the vector, or null, in case it is not present. Alternatively, you can also use .Find() and check whether the length of the resulting vector is zero before attempting to retrieve its first element.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants