1

What I'm looking to do is take an array of numbers which progressively get bigger determine the highest one I can round down to. I'm not sure if that makes sense, I will give an example. Keep in mind I am making the numbers more simple for the sake of explanation, removing the last digit wouldn't work. The array I am using has 100 numbers going into the millions.

int[] breakpoint = new int[] {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
     110, 120, 130, 140, 150, 160, 170, 180, 190, 200};
    int totalValue = 153;
    int valueDisplayed;
         //???
label.Text = valueDisplayed.toString();

So what I would want in this situation is to return a value of 15(the index of the item in the array), so I can then display that value (for example with a label). Surely there's got to be an easy way to do this? I could not find an answer anywhere.

greybeard
  • 2,249
  • 8
  • 30
  • 66
Werter
  • 13
  • 3
  • 3
    I'm not entirely sure what you mean by "round down" here. What exactly is rounded down and where does 15 come from? – 41686d6564 stands w. Palestine May 31 '21 at 10:34
  • 1
    Instead of trying to find. a ready-made answer, just try to solve the problem. The simplest solution would be to iterate until you find a number that's larger than your target and check the previous one to find which is closest. There are certainly more elegant or faster solutions, but that's probably enough to start – Panagiotis Kanavos May 31 '21 at 10:34
  • what do you mean exactly with `the highest one i can round down to`? what is totalValue and why would you like to go from 153 to 15? Can you only display 2 digits? – ozerodb May 31 '21 at 10:36
  • 15 would be the 15th number in the array. By round down i mean is totalValue would be rounded down to the nearest number in the array. If totalValue was for example 19, it would still round to 10, which would be 1. – Werter May 31 '21 at 10:38
  • `The array i am using has 100 numbers going into the millions.` in that case you have to provide far more information. For starters, using an array would be a bad idea. If the numbers are so regular, you wouldn't even have to search the array, you could calculate the index, eg `153/10=15`. Data files with so much data almost always have indexes or other features so you *don't* have to scan everything – Panagiotis Kanavos May 31 '21 at 10:39
  • ok then, as suggested by @PanagiotisKanavos, iterate over the array until you find the number closest to totalValue, then return the index of that number – ozerodb May 31 '21 at 10:40
  • 1
    For moderate amounts of sorted data you can use binary search - start from the "middle" number and check whether it's larger or smaller from the target. If it's larger, check the previous number to see if it's what you want. Otherwise, take the left or right half and try the same way again – Panagiotis Kanavos May 31 '21 at 10:41
  • For *lots* of data though, loading everything in memory may be more expensive than the search itself. Any kind of index structure would allow you to locate just the data page you need to load and search. – Panagiotis Kanavos May 31 '21 at 10:43

3 Answers3

2

You can use Array.BinarySearch which gives you all you need to know:

public static int GetNearestIndex<T>(T[] items, T value)
{
    int index = Array.BinarySearch(items, value);
    if(index >= 0) 
        return index;
    if(index == -1)
        return 0; // is lower than first, so maybe you want to return -1
    return ~index - 1;
}

I'm using the bitwise complement operator to determine the correct index.

.Net Fiddle with some edge cases.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
1

A naive implementation may be good enough

valueDisplayed = breakpoint[Array.FindIndex(breakpoint, v => v > totalValue) - 1];

But you may want to do binary search to speed it up

Charlieface
  • 52,284
  • 6
  • 19
  • 43
0

You can find the index of your round-down breakpoint array using System.Linq.

var index = breakpoint.Where(i => i <= totalValue).ToList().Count - 1;

This line of code will select all itens within your array lower than totalValue, put into a list, and count it's entry. To get the index, just subtract 1 from it.

This solution assumes all entries in breakpoint are in ascending order.

It is the simplest solution I can think of, but it might be computationally expesive, due to searching the whole array.

JeanLColombo
  • 160
  • 6