如何对嵌套类型的数组进行排序?

How do I sort an array of nested types?

我在 Fortran 95 中有以下数据结构:

        type :: timestamp_record
                integer                                 :: year
                integer                                 :: month
                integer                                 :: day
                integer                                 :: hour
                integer                                 :: minute
                integer                                 :: second
        end type
​
        type :: foo_record
                type(timestamp_record)                  :: timestamp
                integer                                 :: foo
                integer                                 :: bar
                integer                                 :: baz
        end type
​
        type(foo_record),dimension(10000)               :: my_array
​

我想按 my_array 排序:

   timestamp%year
   timestamp%month
   timestamp%day
   timestamp%hour
   timestamp%minute
   timestamp%second

我看到有qsort和qsort64可用,但我不知道我应该用什么作为长度。

我也看到需要提供比较函数(类似Cqsort

三个问题:

  1. 在哪里可以找到针对两个或三个字段实施的 qsort 示例?
  2. 即使我想对嵌套的 type 数组进行排序,我也可以使用它吗?
  3. type 结构在 Fortran 中称为 struct 吗?

我无法评论您在哪里可以找到示例代码。这是题外话,但例子确实存在。使用我们搜索。试试像 Github 或 RosettaCode 这样的网站。

但是,最好注意结构通常是如何排序的。您最常创建一个比较函数来比较两个对象并说明它们应该如何排序,哪个应该先行。

例如,来自我的代码

  function CompareWMPoints(Aptr,Bptr) bind(C,name="CompareWMPoints") result(res)
    use iso_c_binding
    integer(c_int)         :: res
    type(c_ptr),value :: Aptr,Bptr
    type(WMPoint),pointer  :: A,B

    call c_f_pointer(Aptr,A)
    call c_f_pointer(Bptr,B)

    if ((A%xi+(A%yj-1)*Prnx+(A%zk-1)*Prnx*Prny) < (B%xi+(B%yj-1)*Prnx+(B%zk-1)*Prnx*Prny)) then
      res = -1_c_int
    else if ((A%xi+(A%yj-1)*Prnx+(A%zk-1)*Prnx*Prny) > (B%xi+(B%yj-1)*Prnx+(B%zk-1)*Prnx*Prny)) then
      res =  1_c_int
    else if (A%distx**2+A%disty**2+A%distz**2 < B%distx**2+B%disty**2+B%distz**2) then
      res = -1_c_int
    else if (A%distx**2+A%disty**2+A%distz**2 > B%distx**2+B%disty**2+B%distz**2) then
      res =  1_c_int
    else
      res =  0_c_int
    end if

  end function CompareWMPoints

这将比较两个对象,AB。您可以引用嵌套在这两个对象中的任何其他结构。比较的结果是一个整数(-1、1 或 0)。

注意:AB是通过C指针传递的,因为使用了Cqsort()。这可以通过使用 Fortran 排序子例程来避免。可以使用 type(...), intent(in) ::,但如果类型不可互操作,那是不合法的。

因为我比较懒所以直接调用了C标准库中的qsort()

  interface
    subroutine qsort(array,elem_count,elem_size,compare) bind(C,name="qsort")
      import
      type(c_ptr),value       :: array
      integer(c_size_t),value :: elem_count
      integer(c_size_t),value :: elem_size
      type(c_funptr),value    :: compare !int(*compare)(const void *, const void *)
    end subroutine qsort !standard C library qsort
  end interface

但您可以调用任何其他使用比较函数的子例程。

使用这些回调函数会带来一定的性能损失,但通常并不那么重要。