在一组数字中寻找最接近的匹配项

25

今天我被问到在一个集合中找到最接近匹配的最佳方法是什么。

例如,你有这样一个数组:

1, 3, 8, 10, 13, ...

离4最近的数字是多少?

集合是数值、无序且可以是任何东西。匹配的数字也是如此。

让我们看看从各种语言中能够得到什么结果。

33个回答

22

J 中的 11 字节:

C=:0{]/:|@-

举例:

>> a =: 1 3 8 10 13
>> 4 C a
3
>> 11 C a
10
>> 12 C a
13

对于普通人的解释:

0{         First element of
]          the right argument
/:         sorted by
|          absolute value 
@          of
-          subtraction

现在只剩下 11 字节了... 那个显式的 @ 链和括号让我感到不安。 - Jimmy

19

更短的 Python 代码:41 个字符

f=lambda a,l:min(l,key=lambda x:abs(x-a))

9

我的Python尝试:

def closest(target, collection) :
    return min((abs(target - i), i) for i in collection)[1]

c=lambda t,l:min((abs(t-i),i) for i in l)[1] - Mike T

5

Groovy 28B

f={a,n->a.min{(it-n).abs()}}

5

以下是一些与C# Linq有关的内容... 有太多的方法可以做到这一点!

decimal[] nums = { 1, 3, 8, 12 };
decimal target = 4;

var close1 = (from n in nums orderby Math.Abs(n-target) select n).First();
var close2 = nums.OrderBy(n => Math.Abs(n - target)).First();

Console.WriteLine("{0} and {1}", close1, close2);

如果您使用列表,将有更多的方法,因为普通数组没有 .Sort() 方法。


4

因为我确实需要这样做,所以这是我的PHP代码:

$match = 33;

$set = array(1,2,3,5,8,13,21,34,55,89,144,233,377,610);

foreach ($set as $fib)
    {
        $diff[$fib] = (int) abs($match - $fib);
    }
$fibs = array_flip($diff);
$closest = $fibs[min($diff)];

echo $closest;

4
假设数值起始于名为T的表格中,该表格包含一个名为N的列,并且我们正在寻找数值4,则在Oracle SQL中需要59个字符:
select*from(select*from t order by abs(n-4))where rownum=1

我使用了select *来减少空格要求。

在 Oracle 中没有类似于“select top 1 * from t order by abs(n-4)”这样的语法吗? - Jimmy
@Jimmy:恐怕不行。必须使用愚蠢的rownum hack或分析功能。也许可以使用分析功能来缩短这个过程。 - WW.

4

PostgreSQL:

select n from tbl order by abs(4 - n) limit 1

如果两个记录共享“abs(4-id)”的相同值,则输出将是不确定的,可能不是一个常数。为了解决这个问题,我建议尝试以下未经测试的猜测:

select n from tbl order by abs(4 - n) + 0.5 * 4 > n limit 1;

这个解决方案的性能大约是O(N log N),其中O(log N)也是可能的,例如:https://dev59.com/snRB5IYBdhLWcg3w-8Ho#8900318


3

就像 Python 一样,Ruby 也有一个用于 Enumerable 的 min 方法,因此您不需要进行排序操作。

def c(value, t_array)
  t_array.min{|a,b|  (value-a).abs <=> (value-b).abs }
end

ar = [1, 3, 8, 10, 13]
t = 4
c(t, ar) = 3

2

上述代码对浮点数无效。
因此,以下是我修改后的 PHP 代码。

function find_closest($match, $set=array()) {
    foreach ($set as $fib) {  
        $diff[$fib] = abs($match - $fib);  
    }  
    return array_search(min($diff), $diff);  
}

$set = array('2.3', '3.4', '3.56', '4.05', '5.5', '5.67');  
echo find_closest(3.85, $set); //return 4.05  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接