在给定数组中查找最接近的数字


21

这是受到我遇到的一个现实世界问题的启发。我很好奇,看看是否有任何聪明的方法可以解决这个问题。

给您两个未排序的数组A和B,每个数组包含任意数量的浮点数。A和B的长度不一定相同。编写一个函数,该函数顺序获取A的元素并在数组B中找到最接近的值。结果必须包含在新数组中。

获胜条件

最短的代码获胜(照常)。



1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳我读到“将A的每个元素四舍五入到B的最近元素”
John Dvorak 2014年

@JanDvorak:好吧,我了解关于取整方向的部分,但是问题并没有具体说明多少位数。
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 2014年

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳舍入到最近的浮点数。答案具有输出从阵列/列表B.漂浮
Orhym

1
数组A和B是否会排序?
级圣河

Answers:


17

APL,13 17

(UTF-8中为21个字节)

B[{↑⍋|⍵-B}¨A]

如果要使用真正的lambda(A作为左参数,B作为右参数):

{⍵[⍺{↑⍋|⍺-⍵}¨⊂⍵]}

怎么运行的:

{...}¨A{...}使用每个A值调用lambda函数(而不是使用A作为数组调用),将结果收集到相同形状的数组中

|⍵-B 计算参数⍵与B中所有变量之间的差的绝对值(-是减法,|是abs)。

↑⍋ 获取最小元素的索引(⍋对返回索引的数组进行排序,↑获取第一个元素)

B[...] 只是按索引获取元素。

该解决方案非常简单,尽管它使用了APL排序功能的奇妙功能,该功能返回置换向量(原始数组中排序元素的索引),而不是排序数组本身。


这是如何运作的?
John Dvorak 2014年

答案解释
钒2014年

你到底怎么知道这个写的?
Martijn 2014年

这就像写中文。对我来说,写外来词或外来字符没有太大区别……
Vovanium 2014年

17

Mathematica-17

#&@@@Nearest@A/@B

它是如何工作的?是的,我承认这里有些作弊,因为Mathematica具有内置的最近功能。其余的很简单,并且关心将结果排列在一维数组中。看起来丑陋只是因为要使其简短而付出的额外努力。


1
哈!欢迎!:)
belisarius博士2014年

6

C#-103 97 87字节

我不确定我是否正确理解了这个问题,但是无论如何这是我的解决方案。 我使用列表而不是数组,因为它使我可以编写较短的代码。

整数数组比整数列表短。

输入:

t(new int[] { 0, 25, 10, 38 }, new int[] { 3, 22, 15, 49, 2 });

方法:

void t(int[]a,int[]b){var e=a.Select(c=>b.OrderBy(i=>Math.Abs(c-i)).First()).ToArray();

输出:

2, 22, 15, 49

如果我的回答不正确,请在下面留下评论。

编辑: @grax指出,现在的问题是关于浮点数。因此,我也想包括他的答案。

95字节(Grax的答案)

float[]t(float[]a,float[]b){return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}

列表也很好。
Orhym 2014年

1
重命名itemi,您将可以确保另外6个字符的安全;)
Aschratt 2014年

@Aschratt非常感谢!
tsavinho 2014年

3
1.该函数没有特别说明要返回新值,但我认为您应该这样做。2.由于问题要求使用浮点数,我认为您应该使用浮点数float[] t(float[] a, float[] b) {return a.Select(d=>b.OrderBy(e=>Math.Abs(e-d)).First()).ToArray();}
Grax32 2014年

@Grax在我写第一个答案时,问题不是关于浮点数的。由于问题已更新,因此我也提供了您的答案。非常感谢你。
tsavinho 2014年

5

R,41个字符

B[apply(abs(outer(A,B,`-`)),1,which.min)]

说明:

outer(A,B,`-`)为A的每个元素x计算差异x-B,并将结果输出为矩阵(尺寸为length(A)x length(B))。
which.min选择最小数字的索引。在矩阵的每行上
apply(x, 1, f)应用函数。 因此返回A的每个元素与向量B的元素之间的最小绝对差的索引。fx
apply(abs(outer(A,B,`-`)),1,which.min)

用法:

> A <- runif(10,0,50)
> B <- runif(10,0,50)
> A
[1] 10.0394987 23.4564467 19.6667152 36.7101256 47.4567670 49.8315028  2.1321263 19.2866901  0.7668489 22.5539178
> B
[1] 44.010174 32.743469  1.908891 48.222695 16.966245 23.092239 24.762485 30.793543 48.703640  6.935354
> B[apply(abs(outer(A,B,`-`)),1,which.min)]
[1]  6.935354 23.092239 16.966245 32.743469 48.222695 48.703640  1.908891 16.966245  1.908891 23.092239

5

果酱-14

q~
f{{1$-z}$0=\;}
p

主要代码在第二行,其余代码用于使用标准输入和漂亮输出。

http://cjam.aditsu.net/上尝试

说明:

q~读取并评估输入
f{...},为第一个数组的每个元素和下一个对象(即第二个数组)的每个块执行该块,将结果收集到一个数组中
{...}$,然后使用该块对第二个数组进行排序,以计算出每个项目的键值
1$复制当前第一个数组中的项目
-z减去然后取绝对值
0=,将排序后的数组的第一个值(具有最小键的
\;那个)丢弃,第一个数组中的项目丢弃,并
p打印结果的字符串表示形式

例子(从其他答案中得到启发):

输入:[10.1 11.2 12.3 13.4 9.5] [10 12 14]
输出:[10 12 12 14 10]

输入:[0 25 10 38] [3 22 15 49 2]
输出:[2 22 15 49]


4

Javascript(E6)54 56 59

最小化距离。使用正方形而不是abs可以节省字符。
编辑代数...
编辑无用的赋值(不带功能定义的测试的其余部分)

F=(A,B)=>A.map(a=>B.sort((x,y)=>x*x-y*y+2*a*(y-x))[0])

F=(A,B)=>D=A.map(a=>B.sort((x,y)=>((x-=a,y-=a,x*x-y*y))[0])

测试

F([10.1, 11.2, 12.3, 13.4, 9.5],[10, 12, 14])

结果: [10, 12, 12, 14, 10]


1
D=不需要,因为会map返回一个新数组。替代(相同长度)的排序功能:(x,y)=>(x-=a)*x-(y-=a)*y
nderscore 2014年

4

Python 3.x-55个字符

f=lambda a,b:[min((abs(x-n),x)for x in b)[1]for n in a]

ab是输入数组,而所需的数组是表达式的结果。


我编辑了答案以使其具有功能性,因为问题需要功能。
user80551 2014年

3

哈斯克尔,55岁

c a b=[[y|y<-b,(y-x)^2==minimum[(z-x)^2|z<-b]]!!0|x<-a]

最初,我想使用minimumBycomparing,但是由于这些不在Prelude中,因此花了很多字符才能使它们合格。还从其他答案中窃取了平方的想法以剃除角色。


3

PowerShell的-44

$a|%{$n=$_;($b|sort{[math]::abs($n-$_)})[0]}

随着$a$b设置为:

$a = @(36.3, 9, 50, 12, 18.7, 30)
$b = @(30, 10, 40.5, 20)

输出是

40.5, 10, 40.5, 10, 20, 30

你可以使用花车在本例中,以明确它处理花车太
贝贝

@bebe-谢谢您的更新,以使其更加清楚。
雷纳特2014年

-3个字节:$a|%{$n=$_;($b|sort{($n-$_)*($n-$_)})[0]}
mazzy

2

Ruby,40岁

f=->a,b{a.map{|x|b.min_by{|y|(x-y)**2}}}

与Python答案相同,但平方比我想得到绝对价值的任何方式都要麻烦。


2

Pyth- 12 11字节

注意:Pyth比这个挑战要年轻得多,因此此答案不符合要求。

简单的方法,使用o命令功能获得最小距离并将m其应用于列表a

mho.a-dNQvz

m    vz    Map over evaled first input and implicitly print
 ho Q      Minimal mapped over evaled second input
  .a-      Absolute difference
   d       Lambda param 1
   b       Lambda param 2

在这里在线尝试


@Jakube哦,是的,抱歉。
Maltysen

2

TI-BASIC,24岁

∟A+seq(min(∟B+i²∟A(N)),N,1,dim(∟A

与APL不太接近,但是使用的功能较弱-它不使用“排序依据”或“最小索引”功能。TI-BASIC的缺点是缺少这些功能和多维数组。

取消高尔夫:

seq(       ,N,1,dim(∟A           #Sequence depending on the Nth element of list A
    ∟A(N)+min(   +0i)            #Number with minimum absolute value, add to ∟A(N)
              ∟B-∟A(N)           #Subtracts Nth element of ∟A from all elements of B

min(函数有两种行为:与实数或列表一起使用时,它给出最小值;但是,与复数或列表一起使用时,它给出绝对值最小的值。加0i或乘以i^2使解释器得出使用第二种行为,因此min(1,-2)return,-2min(1+0i,-2+0i)return 1


1

Fortran 90:88

function f();integer::f(size(a));f(:)=[(b(minloc(abs(a(i)-b))),i=1,size(a))];endfunction

这要求contain在完整程序中进行编辑:

program main
   real :: a(5), b(3)
   integer :: i(size(a))
   a = [10.1, 11.2, 12.3, 13.4, 9.5]
   b = [10, 12, 14]
   i = f()
   print*,i
 contains
   function f()
     integer :: f(size(a))
     f(:)=[(b(minloc(abs(a(i)-b))),i=1,size(a))]
   end function
end program main

方括号声明一个数组,而while (...,i=)表示隐式do循环;然后,我返回b为其a(i)-b最小化的元素的值。


1

Matlab:48

f=@(a)B(abs(B-a)==min(abs(B-a)));C=arrayfun(f,A)

假定AB是工作空间中的一维矩阵,最终结果C在工作空间中。这也可能在Octave中也适用。条件索引使此操作变得相当简单。


0

C 144163

#define f float
f T, *C, m;
f *q(f *A, f *B, int S, f s)
{
    if(m) 
        return abs(T - *A) - abs(T - *B);
    for ( 
        C = malloc(S * 4);
        m = S--;
        C[S] = *B
    ) 
        T = A[S], 
        qsort(B, s, 4, q);
    return C;
}

好的,我认为这个小代码需要解释。

起初,我尝试使用两个级别的for循环来完成此工作,以找到最小差并将当前值设置为B值的最小值。这是非常基本的。

使用qsort和比较器功能可以达到相同的目的。我根据差异而不是B的元素将其排序为B。这么少的算法功能太多。因此,函数q现在有两个作用。首先,它是算法本身,其次是(当qsort调用时)比较器。为了两国之间的交流,我必须声明全局变量。

m表示它处于比较器状态还是状态。

例:

float A[] = {1.5, 5.6, 8.9, -33.1};
float B[] = {-20.1, 2.2, 10.3};
float *C;

C = q(A, B, sizeof(A)/sizeof(*A), sizeof(B)/sizeof(*B));
// C holds 2.2,2.2,10.3,-20.1

166/163是否计算空格?
Kyle Kanos 2014年

当然不是。空格和换行符是为了便于理解。
bebe 2014年

0

GolfScript,49个字节

注意:这是部分解决方案。我正在努力使其成为一个完整的解决方案

{{\.@\.[.,,\]zip@{[\~@-abs]}+%{~\;}$0=0==}%\;}:f;

是。GolfScript确实支持浮点。在这里尝试。例:

# B is [-20.1 2.2 10.3]
[-201 10 -1?*
22 10 -1?*
103 10 -1?*]

# A. No floating point numbers allowed here.
# This is because 1.5{}+ (where the 1.5 is a
# single floating point number, not 1.5,
# which would be 1 1 5) results in the block
# {1.5 }, which leads to 1 1 5 when executed
[1 5 9 -30]

输出:

[2.2 2.2 10.3 -20.1]

0

C#262

程序找到最小的差异,并从数组B中保存最接近的值。我将很快打高尔夫球。

List<float> F(List<float> a, List<float> b)
{
List<float> c = new List<float>();
float diff,min;
int k;
for(int i=0; i<a.Count;i++)
{
diff=0;
min=1e6F;
k = 0;
for(int j=0; j<b.Count;j++)
{
diff = Math.Abs(a[i] - b[j]);
if (diff < min)
{
min = diff;
k = j;
}
}
c.Add(b[k]);
}
return c;
}

带有测试代码的完整程序

using System;
using System.Collections.Generic;
public class JGolf
{
    static List<float> NearestValues(List<float> a, List<float> b)
    {
        List<float> c = new List<float>();
        float diff,min;
        int k;
        for(int i=0; i<a.Count;i++)
        {
            diff=0;
            min=1e6F;
            k = 0;
            for(int j=0; j<b.Count;j++)
            {
                diff = Math.Abs(a[i] - b[j]);
                if (diff < min)
                {
                    min = diff;
                    k = j;
                }
            }
            c.Add(b[k]);
        }
        return c;
    }

    public static void Main(string[] args)
    {
        List<float> A = RandF(8413);
        Console.WriteLine("A");
        Print(A);
        List<float> B = RandF(9448);
        Console.WriteLine("B");
        Print(B);

        List<float> d = JGolf.NearestValues(A, B);
        Console.WriteLine("d");
        Print(d);
        Console.ReadLine();
    }

    private static List<float> RandF(int seed)
    {
        Random r = new Random(seed);
        int n = r.Next(9) + 1;
        List<float> c = new List<float>();
        while (n-- > 0)
        {
            c.Add((float)r.NextDouble() * 100);
        }
        return c;
    }

    private static void Print(List<float> d)
    {
        foreach(float f in d)
        {
            Console.Write(f.ToString()+", ");
        }
    }
}

0

C#:120

Linq很棒:

float[] t(float[] A, float[] B){return A.Select(a => B.First(b => Math.Abs(b-a) == B.Min(c=>Math.Abs(c-a)))).ToArray();}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.