Trying to understand sort!(), findfirst()

So far, this community is giving a lot of helps to answer beginner level julialang question. I am still in the early stage of learning julialang, so here I got a few new questions that might need community help. I am a little confused about using sort!(), findfirst() function. Here is the code line that I got stuck:

for i=1:n:
    ps_id=[] # psid::Vector[Int]
    cns = [] # cns::Tuple{Integer, Vector}[]
    cs = (i, sort!(ps_id))
    if findfirst(cns .== cs) ==0
        push!(cns, cs)
    end
end

Does anyone provide possible examples to understand the above codes explicitly? what’s the corresponding pythonic code for those? Any thoughts?

since I am more comfortable with python, so this is my attempt to do same thing in pythonic way:

for i in range(1, n):
    ps_id=[] # psid::Vector[Int]
    cns = [] # cns::Tuple{Integer, Vector}[]
    # cs = (i, sort!(ps_id)) # julialang
    cs = np.sort(ps_id[i]) # I am not quire sure this pythonic way
    if findfirst(cns .== cs) ==0
        cns.append(cs)

in my pythonic attempt, I am not quite sure I did right for pythonic code such as cs = np.sort(ps_id[i]) is actually as same as cs = (i, sort!(ps_id)). Can anyone point me out sort!() function bit clear?

I think I got confused about using findfirst() in julialang, not sure how should I do same thing in python? Does anyone have better ideas? Thanks!

I’m not exactly clear on what your question is, but the following examples might be helpful

julia> x=randn(5)
5-element Array{Float64,1}:
  0.7434739264175095
 -0.3395323336044915
  0.13788529694661847
 -0.27519785275734027
  1.0434216847847444

julia> sort!(x)
5-element Array{Float64,1}:
 -0.3395323336044915
 -0.27519785275734027
  0.13788529694661847
  0.7434739264175095
  1.0434216847847444

julia> x
5-element Array{Float64,1}:
 -0.3395323336044915
 -0.27519785275734027
  0.13788529694661847
  0.7434739264175095
  1.0434216847847444

julia> isone
isone (generic function with 13 methods)

julia> findfirst(isone, x .< 0.0)
1

julia> findfirst(isone, x .> 0.0)
3

1 Like

Thanks for the heads up. I am trying to understand the julia code with pythonic alternative, such as cs=(i, sort!(ps_id)) is as same as this pythonic code: cs=np.sort(ps_id[i]). I am not sure role of findfirst() in if condiction: if findfirst(cns .==cs)==0. Do you have any clue this can be written in the plain pythonic way? what is the meaning of .==? any idea?

compares cns and cs for equality, takes the first thing that does NOT match, i.e. the first item that is NOT in cns, and adds that to the array cns. Or at least I’m pretty sure that’s what it does.

.== automatically applies the ‘==’ operator to arrays. The ‘.’ notation is important to understand, please see

[Single- and multi-dimensional Arrays · The Julia Language]

1 Like

To add to @purplishrock’s answers, you can check functions’ docs by typing ? at the REPL (to go in “help” mode) and get some helpful info on the function. For example,

help?> sort!
search: sort! partialsort! sortperm! partialsortperm! setproperty! sort sortperm sortslices SortedSet sorted_rank SortedDict

  sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward)


  Sort the vector v in place. QuickSort is used by default for numeric arrays while MergeSort is used for other arrays. You
  can specify an algorithm to use via the alg keyword (see Sorting Algorithms for available algorithms). The by keyword lets
  you provide a function that will be applied to each element before comparison; the lt keyword allows providing a custom
  "less than" function; use rev=true to reverse the sorting order. These options are independent and can be used together in
  all possible combinations: if both by and lt are specified, the lt function is applied to the result of the by function;
  rev=true reverses whatever ordering specified via the by and lt keywords.
# and much more (cut for clarity, but try it yourself)

To your specific questions, maybe an example with Ints is clearer. The Julia functions sort! and findfirst are pretty much explicit:

  • sort!(x) sorts x by mutating it (the ! at the end indicates mutation):

    julia> x = rand(1:1000, 5)
    5-element Array{Int64,1}:
     200
     247
      15
     878
     441
    
    julia> sort!(x); x
    5-element Array{Int64,1}:
      15
     200
     247
     441
     878
    
  • findfirst(y) finds the first index of y that is true. I can use .== to find the first element equal to some value (the dot . means element-wise and == means “is equal”, so .== means it tests equality of each element against what is on the other side). For example, I can find the first element equal to 2 with findfirst(x .== 2), as in this example:

    julia> x = rand(1:3, 5)
    5-element Array{Int64,1}:
     3
     2
     2
     3
     3
    
    julia> x .== 2
    5-element BitArray{1}:
     0
     1
     1
     0
     0
    
    julia> findfirst(x .== 2)
    2
    

    Alternatively, I can have a function as the first argument of findfirst, and Julia will apply that function to the array as it looks for that first index. Here I could use the function ==(2) which is testing equality with 2:

    julia> findfirst(==(2), x)
    2
    

    but I personally prefer the findfirst(x .== 2) version.

Otherwise, note that in your code

findfirst(cns .== cs) == 0

will never return true since indexing start at 1 in Julia (so findfirst can only return an integer greater or equal to 1, or nothing if no element is found).

4 Likes