Wolfram mathematica 查找Mathematic列表中大于阈值的第一个元素

Wolfram mathematica 查找Mathematic列表中大于阈值的第一个元素,wolfram-mathematica,Wolfram Mathematica,我想知道如何获得大于给定阈值的(已排序)列表的第一个元素 我不太了解Mathematica中的列表操作函数,也许有人能给我一个有效的技巧。做你需要的事情,并且会保持一致,尊重列表的原有顺序: Select[list, # > threshold &, 1] 例如: In[1]:= Select[{3, 5, 4, 1}, # > 3 &, 1] Out[1]= {5} 您可以在第二个参数中提供所需的任何阈值或标准函数 第三个参数只指定一个(即第一个)匹配的元素

我想知道如何获得大于给定阈值的(已排序)列表的第一个元素

我不太了解Mathematica中的列表操作函数,也许有人能给我一个有效的技巧。

做你需要的事情,并且会保持一致,尊重列表的原有顺序:

Select[list, # > threshold &, 1]
例如:

In[1]:= Select[{3, 5, 4, 1}, # > 3 &, 1]

Out[1]= {5}
您可以在第二个参数中提供所需的任何阈值或标准函数

第三个参数只指定一个(即第一个)匹配的元素


希望有帮助

您可能还需要查看TakeWhile[]和纵向[]


使用
Select
可以解决问题,但如果您关心效率,这是一个糟糕的解决方案<代码>选择遍历列表的所有元素,因此所需时间与列表长度成线性关系。 既然您说列表是有序的,那么使用它会更好,它将在列表大小为对数的时间内工作。表达式(edit:由于我编写的上一个表达式没有正确处理列表中的重复元素,我做了一个小的调整。另一个编辑:当阈值本身作为重复元素出现在列表中时,这仍然不起作用,请参阅注释):

将为您提供所需元素的索引。如果所有元素都小于阈值,则将得到列表的长度加上一。
p、 在使用
BinarySearch
之前,不要忘记调用
Needs[“Combinatica'”

list /. {___, y_ /; y > 3, ___} :> {y}
比如说

{3, 5, 4, 1} /. {___, y_ /; y > 3, ___} :> {y}

{5}

Joe在他的文章中正确地指出,人们期望二进制搜索技术比
Select
更快,后者似乎只是进行线性搜索,即使列表已排序:

ClearAll[selectTiming]
selectTiming[length_, iterations_] := Module[
    {lst},
    lst = Sort[RandomInteger[{0, 100}, length]];
    (Do[Select[lst, # == 2 &, 1], {i, 1, iterations}] // Timing // 
     First)/iterations
  ]

(出于演示目的,我任意将阈值设置为2)

但是,Combinatica中的
BinarySearch
函数a)不合适(它返回的元素与请求的元素不匹配,但不是第一个元素(最左边的),这就是问题所在

为了获得大于阈值的最左侧元素,给定一个有序列表,我们可以递归地执行以下操作之一:

binSearch[lst_,threshold_]:= binSearchRec[lst,threshold,1,Length@lst]

(*
return position of leftmost element greater than threshold
breaks if the first element is greater than threshold
lst must be sorted
*)
binSearchRec[lst_,threshold_,min_,max_] :=
    Module[{i=Floor[(min+max)/2],element},
        element=lst[[i]];
        Which[
            min==max,max,
            element <= threshold,binSearchRec[lst,threshold,i+1,max],
            (element > threshold) && ( lst[[i-1]] <= threshold ), i,
            True, binSearchRec[lst,threshold,min,i-1]
        ]
    ]
产生

因此,速度更快,伸缩性更好

实际上没有必要编译它,但我还是编译了

总之,不要对长列表使用
Select

我的回答到此结束。下面是一些关于手工或通过Combinatica包进行二进制搜索的评论

我比较了一个(编译的)短例程进行二进制搜索的速度与
combinatica
中的
BinarySearch
的速度。请注意,这并不符合问题的要求(也不符合
BinarySearch
中的
BinarySearch
),我上面给出的代码确实如此

二进制搜索可以迭代地实现为

binarySearch = Compile[{{arg, _Integer}, {list, _Integer, 1}},
           Module[ {min = 1, max = Length@list,
                 i, x},
               While[
                    min <= max,
                    i = Floor[(min + max)/2];
                    x = list[[i]];
                    Which[
                         x == arg, min = max = i; Break[],
                         x < arg, min = i + 1,
                         True, max = i - 1
                     ]
                ];
               If[ 0 == max,
                   0,
                   max
               ]
           ], 
        CompilationTarget -> "C", 
        RuntimeOptions -> "Speed"
];
让我们比较两个二进制搜索例程。重复50000次:

Needs["Combinatorica`"]
Do[binarySearch[2, lst], {i, 50000}] // Timing
Do[BinarySearch[lst, 2], {i, 50000}] // Timing
(*
{0.073437, Null}
{4.8354, Null}
*)

所以手写的更快,因为实际上二进制搜索只访问列表中的6-7个点来获取这些参数(例如,
{500000,250000,125000,62500,31250,15625,23437}
),很明显,区别只是开销;例如,
BinarySearch
可能更通用,或者没有编译。

仅供将来参考,从v10开始,您可以使用

它增加了一些细节,例如返回
缺少的[]
或默认值

从文档中:

SelectFirst[{e1,e2,…},crit]
给出第一个
ei
,如果没有找到,则
crit[ei]
True
,或者
缺少[“NotFound”]

SelectFirst[{e1,e2,…},crit,default]
如果没有
ei
,则给出
default
,从而
crit[ei]
True

对于您的具体情况,您可以使用:

SelectFirst[list, # > threshold &]

为什么需要天花板?而且,这不会返回第一个(最左边的)匹配元素。我写了一些东西,在我的答案中使用二进制搜索来获得最左边的元素。我将
上限
函数更改为
下限
函数,以正确处理列表中的重复元素。这是必需的,因为如果阈值介于元素n和n+1之间,则
二进制搜索
返回n+1/2.我编写的代码工作得很好,确实返回了第一个(最左边的)元素,该元素大于阈值(请求的不是匹配的元素)。它也比他在回答中提供的代码@acl简单得多。奇怪的是,
lst={1,3,3,3,3,3,4,5};Floor[BinarySearch[lst,3]+1]
给出了6和lst[[6]]不大于阈值,但与我下面给出的
binarySearch
例程相同(但速度大约快50倍)。我的答案中的复杂代码只是带有稍微修改的终止条件的二进制搜索(以便实际获得比阈值大的最左边的元素)。或者至少它基本上正确地找到了正确的元素:)你是对的@acl,很抱歉怀疑你。如果阈值作为循环元素出现在列表中,
BinarySearch
从循环序列的中间给出一个索引,这是不好的。太糟糕了,我们必须编写Mathematica已经提供的函数的我们自己的版本,只是因为它没有给我们控制权关于终止条件。感谢投票。更令人遗憾的是,即使一个人需要的正是
BinarySearch
所做的,手工编写和编译会使它更快。但这可能是因为
BinarySearch
Combinatica
的一部分,而不是一个内置函数er但请尝试
tmp=Sort[RandomInteger[{01000},100000]
binarySearch = Compile[{{arg, _Integer}, {list, _Integer, 1}},
           Module[ {min = 1, max = Length@list,
                 i, x},
               While[
                    min <= max,
                    i = Floor[(min + max)/2];
                    x = list[[i]];
                    Which[
                         x == arg, min = max = i; Break[],
                         x < arg, min = i + 1,
                         True, max = i - 1
                     ]
                ];
               If[ 0 == max,
                   0,
                   max
               ]
           ], 
        CompilationTarget -> "C", 
        RuntimeOptions -> "Speed"
];
lst = Sort[RandomInteger[{0, 100}, 1000000]];
Needs["Combinatorica`"]
Do[binarySearch[2, lst], {i, 50000}] // Timing
Do[BinarySearch[lst, 2], {i, 50000}] // Timing
(*
{0.073437, Null}
{4.8354, Null}
*)
SelectFirst[list, # > threshold &]