[英]Best way to find values in range
I have a collection of values: 我有一些价值观:
I expect input from users in the for of [44] for example. 例如,我希望用户输入[44]中的。 What would be the most eloquent way to determine in which item the value falls?
确定该值属于哪一项的最雄辩的方法是什么?
I can write a switch statement to match a case > < or an if...statement but neither of these in my opinion is eloquent enough. 我可以编写一个switch语句来匹配一个case> <或一个if ...语句,但是我认为这两个都不是很能说明问题。
Update 更新资料
I'm looking for a neat and tidy way of finding the range in which my user's input fall, using something like LAMDBA for example: 我正在寻找一种整洁的方法来查找用户输入范围,例如使用LAMDBA之类的方法:
List<int>().Find(x => x.WithinRange(range))
Or something like that. 或类似的东西。
Something like this as an extension: 像这样的扩展:
public static int WithinRange(this int value)
{
if (value < 0) return 0;
if (value < 21) return 1;
return (value - 1) / 10;
}
without if
statements 没有
if
语句
public static int WithinRange(this int value)
{
return (value < 0) ? 0
: (value < 21) ? 1
: (value - 1) / 10;
}
usage: 用法:
collection.Find(x => x.WithinRange(range))
If your ranges are consecutive, as in your example (ie there are no gaps), you can store their endpoints in an array, like this: 如果您的范围是连续的,例如您的示例(即没有间隙),则可以将它们的端点存储在数组中,如下所示:
var endpoints = new[] {20, 30, 40, 60, 90};
Note that the endpoints are sorted. 请注意,端点已排序。 You can now use a binary search method to find the insertion point of 44 in this array, which is 3, will be returned (binary search will return bitwise complement of 3; you'd need to apply
~
to get the actual value). 现在,您可以使用二进制搜索方法在该数组中找到插入点44,该插入点将返回3(二进制搜索将返回3的按位补码;您需要应用
~
以获取实际值)。
There you go: 你去了:
int GetRange(int value)
{
return (value > 30) ? 3 :
(value > 20) ? 2 :
(value > 0) ? 1 :
0;
}
No ifs! 不,如果!
Just loop over the ranges and see if the value falls within the range... 只需循环遍历范围,看看该值是否在范围内...
var ranges = new[]
{
Tuple.Create(0, 20),
Tuple.Create(21, 30),
Tuple.Create(31, 40),
Tuple.Create(41, 50),
// ...
};
var number = 44;
for (int i = 0; i < ranges.Length; i++)
{
var range = ranges[i];
if (number >= range.Item1 && number <= range.Item2)
{
var theIndex = i + 1;
// do something with theIndex
}
}
You could just manipulate the inputs: 您可以操纵输入:
int input = //Whatever the input is
int index = (input-1)/10;
Assuming integer input, and that your array is indexed as indicated. 假设输入为整数,并且您的数组已按指示建立索引。
UPDATE : I know this is an overkill but it might give you some ideas. 更新 :我知道这太过分了,但可能会给您一些想法。 As I undestand, you already know how to solve this problem, but you are just looking for a "prettier" solution:
我不理解,您已经知道如何解决此问题,但是您只是在寻找“更漂亮”的解决方案:
public class Range
{
public int Left { get; set; }
public int Right { get; set; }
public string Title { get; set; }
public Range(int left, int right, string title) { Left = left; Right = right; Title = title; }
public bool Contains(int x) { return Left <= x && x <= Right; }
}
void Main()
{
var x = 15;
var ranges = new[] {
new Range(0, 10, "A"),
new Range(11, 20, "B")
};
var foo = ranges.Where(r => r.Contains(x)).Single();
Console.Write(foo.Title);
}
My previous suggestion : For
statement is ok but I prefer LINQ :) 我以前的建议 :
For
声明是确定的,但我更喜欢LINQ :)
var x = 15;
var ranges = new[] { Tuple.Create(0, 10), Tuple.Create(11, 20) };
var range = ranges.Where(r => r.Item1 <= x && r.Item2 >= x );
Console.Write(range.Item1);
Console.Write(range.Item2);
Less efficient .NET 3.5 alternative variation of @Jeff Mercado's answer: @Jeff Mercado的答案效率较低的.NET 3.5替代版本:
var ranges = new[]
{
Enumerable.Range(0, 20),
Enumerable.Range(21, 30),
Enumerable.Range(31, 40),
Enumerable.Range(41, 50),
// ...
};
var number = 44;
for (int i = 0; i < ranges.Length; i++)
{
var range = ranges[i];
if (range.Contains(number))
{
var theIndex = i + 1;
// do something with theIndex
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.