findfirst 这个函数的用法


#1

findfirst这个函数是从数组的头开始搜索的吗?
怎么指定从特殊位置开始搜索?比如一个数组十个元素,但是我想从第5个开始搜索


#2

那就裁一下数组

julia> arr = [i for j=1:2 for i=1:3]
6-element Array{Int64,1}:
 1
 2
 3
 1
 2
 3

julia> findfirst(isequal(2), arr[3:end])
3

julia> arr[3+3]
3

julia> findfirst(isequal(2), arr)
2

julia> arr[2]
2

#3

裁数组本身这个操作更加耗时,总用时都不是一个数量级了。


#4

可以用 findnext 吗?


#5

这里用 @view 虽然目前还会多分配点内存、慢一些,但时间是差不多的。

julia> arr = [i for j=1:2 for i=1:80_000_000];

julia> sizeof(arr) / 1024^3 # GB
1.1920928955078125

julia> @btime findfirst(isequal(80_000_000), arr)
  65.163 ms (1 allocation: 16 bytes)
80000000

julia> @btime findfirst(isequal(80_000_000), @view arr[80_000_000+1:end])
  67.589 ms (4 allocations: 112 bytes)
80000000

#6

这个就回到了我的第一个问题,findfirst这个函数并不是从头开始搜索的。具体是用什么方法搜索就不晓得了。


#7

julia 的标准库都是用 julia 自己写的,先确定函数签名,再去 github 上看源代码就好了。

julia> arr = [i for j=1:2 for i=1:3];

julia> findfirst(isequal(2), arr)
2

julia> @which findfirst(isequal(2), arr)
findfirst(testf::Function, A::Union{AbstractString, AbstractArray}) in Base at array.jl:1754
findfirst(testf::Function, A::Union{AbstractArray, AbstractString}) =
    findnext(testf, A, first(keys(A)))

https://github.com/JuliaLang/julia/blob/2d5741174ce3e6a394010d2e470e4269ca54607f/base/array.jl#L1754-L1755

julia> @which findnext(isequal(2), arr, 1)
findnext(testf::Function, A, start) in Base at array.jl:1699
function findnext(testf::Function, A, start)
    l = last(keys(A))
    i = start
    i > l && return nothing
    while true
        testf(A[i]) && return i
        i == l && break
        # nextind(A, l) can throw/overflow
        i = nextind(A, i)
    end
    return nothing
end

https://github.com/JuliaLang/julia/blob/2d5741174ce3e6a394010d2e470e4269ca54607f/base/array.jl#L1698-L1709

看源码确实应该直接用 findnext

julia> arr = [i for j=1:2 for i=1:80_000_000];

julia> using BenchmarkTools

julia> @btime findfirst(isequal(80_000_000), arr)
  73.526 ms (1 allocation: 16 bytes)
80000000

julia> @btime findfirst(isequal(80_000_000), @view arr[80_000_000+1:end])
  75.842 ms (4 allocations: 112 bytes)
80000000

julia> @btime findnext(isequal(80_000_000), arr, 1)
  65.105 ms (1 allocation: 16 bytes)
80000000

julia> @btime findnext(isequal(80_000_000), arr, 80_000_000+1)
  64.821 ms (1 allocation: 16 bytes)
160000000

#8

欧 终于有人看见我说的话了