如何对嵌套类型的数组进行排序?
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
)
三个问题:
- 在哪里可以找到针对两个或三个字段实施的
qsort
示例?
- 即使我想对嵌套的
type
数组进行排序,我也可以使用它吗?
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
这将比较两个对象,A
和 B
。您可以引用嵌套在这两个对象中的任何其他结构。比较的结果是一个整数(-1、1 或 0)。
注意:A
和B
是通过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
但您可以调用任何其他使用比较函数的子例程。
使用这些回调函数会带来一定的性能损失,但通常并不那么重要。
我在 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
)
三个问题:
- 在哪里可以找到针对两个或三个字段实施的
qsort
示例? - 即使我想对嵌套的
type
数组进行排序,我也可以使用它吗? 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
这将比较两个对象,A
和 B
。您可以引用嵌套在这两个对象中的任何其他结构。比较的结果是一个整数(-1、1 或 0)。
注意:A
和B
是通过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
但您可以调用任何其他使用比较函数的子例程。
使用这些回调函数会带来一定的性能损失,但通常并不那么重要。