views:

281

answers:

5

How do I specify a custom code for comparison when finding a minimal element in my Array?

For example, I have two arrays:

int[] a = new int[] {3, 6, 8};
int[] b = new int[] {9, -2, 5};

I want to figure out, what would be the minimal ratio of the elements with respective indexes (i.e. find minimum of 3/9, 6/(-2) and 8/5) and then return the index. I'm already aware of Array.Min(), but I wonder if it's possible to make any sort of it's customization.

+2  A: 

Perhaps something like this:

double smallest = double.MaxValue;
int smallestIndex = 0;

for (int i = 0; i < (a.Length > b.Length ? b.Length : a.Length); i++)
{
    if ((double)a[i] / b[i] < smallest)
    {
        smallest = (double)a[i] / b[i];
        smallestIndex = i;
    }
}

smallestIndex will contain the index of the smallest ratio at the end.

Andy West
+1  A: 

with linq you could do this:

            int customMin = a.Select((v, i) => new { a = v, b = b[i] })
                .Select(x => x.a / x.b)
                .Min();

the first select merges the two lists into on, the second select calculates your custom mertic, then we call min to get the minimum.

AndreasN
Your solution does not yield the index.
Yann Schwartz
+2  A: 

Using linq to get the minimal value AND the index, you could look at this answer:

http://stackoverflow.com/questions/914109/how-to-use-linq-to-select-object-with-minimum-or-maximum-property-value

Using Jon Skeet extension method, you could then write

var result = Enumerable.Range(0,a.Length)
     .Select(i => new {Value = a[i]/b[i], Index = i})
     .MinBy(r => r.Value);

(you'll have to watch out for 0's in b)

Yann Schwartz
It's LINQ, but Andy's answer is more straightforward, if not as estheticaelly pleasant.
Yann Schwartz
+1 for providing answer in LINQ, AND acknowledging that LINQ isn't always the most straightforward. Also, nice job noticing potential div by 0. I didn't see that.
Andy West
+1  A: 

You could use linq to 'zip' the two sequences together, order them by their ratio and select the first index:

a.Select((item, index) => {new { A = item, B = b[index], Idx = index })
    .OrderBy(i => (double)i.A / i.B)
    .Select(i => i.Idx)
    .First();
Lee
+1 For the elegance. It's in O(n Log n) though.
Yann Schwartz
Yes, I'd recommend Andy's answer but I thought this was quite nice too
Lee
A: 

don't forget about the SortedList Class

serhio