Fortran读取两文件并输出相同值至新文件的实现求助
解决思路:从两个文件提取共同数值并写入新文件
嘿,我懂你遇到的麻烦了——用双重DO循环逐个比对数组元素的思路本身没问题,但要么是循环逻辑没捋顺导致匹配失效,要么数据量大的时候效率低到让人头疼。下面给你两种实用的实现方案,看你提到DO语句,我默认用Fortran来写示例,其他类似语言也可以参考这个逻辑:
方案1:排序+双指针法(高效且通用)
这种方法把时间复杂度从双重循环的O(n*m)降到O(n log n + m log m),适合大多数场景,尤其是数值可以排序的情况:
program extract_common_values implicit none integer, allocatable :: arr1(:), arr2(:), common_vals(:) integer :: i, j, count, n1, n2, u1, u2, u3 character(len=25) :: f1 = "input1.txt", f2 = "input2.txt", f3 = "common_output.txt" ! 第一步:读取第一个文件的所有数值 open(newunit=u1, file=f1, status="old", action="read") n1 = 0 do read(u1, *, iostat=i) if (i /= 0) exit n1 = n1 + 1 end do rewind(u1) allocate(arr1(n1)) do i = 1, n1 read(u1, *) arr1(i) end do close(u1) ! 第二步:读取第二个文件的所有数值 open(newunit=u2, file=f2, status="old", action="read") n2 = 0 do read(u2, *, iostat=i) if (i /= 0) exit n2 = n2 + 1 end do rewind(u2) allocate(arr2(n2)) do i = 1, n2 read(u2, *) arr2(i) end do close(u2) ! 第三步:对两个数组排序 call bubble_sort(arr1, n1) call bubble_sort(arr2, n2) ! 第四步:双指针找共同元素 i = 1 j = 1 count = 0 allocate(common_vals(min(n1, n2))) ! 预分配最大可能空间 do while (i <= n1 .and. j <= n2) if (arr1(i) == arr2(j)) then count = count + 1 common_vals(count) = arr1(i) ! 跳过重复元素(避免重复写入相同值) do while (i <= n1 .and. arr1(i) == common_vals(count)) i = i + 1 end do do while (j <= n2 .and. arr2(j) == common_vals(count)) j = j + 1 end do else if (arr1(i) < arr2(j)) then i = i + 1 else j = j + 1 end if end do ! 裁剪数组到实际匹配数量 if (count > 0) then call move_alloc(common_vals, common_vals(1:count)) else deallocate(common_vals) end if ! 第五步:写入结果文件 open(newunit=u3, file=f3, status="replace", action="write") if (allocated(common_vals)) then do i = 1, count write(u3, *) common_vals(i) end do end if close(u3) contains ! 冒泡排序子程序(如果需要更快的可以换成快速排序) subroutine bubble_sort(arr, len) integer, intent(inout) :: arr(:) integer, intent(in) :: len integer :: k, l, temp do k = 1, len-1 do l = 1, len-k if (arr(l) > arr(l+1)) then temp = arr(l) arr(l) = arr(l+1) arr(l+1) = temp end if end do end do end subroutine bubble_sort end program extract_common_values
方案2:哈希集合法(适合大数据量,无需排序)
如果你的编译器支持Fortran 2008及以上的哈希集合(比如GCC的hash_map模块),这种方法的查找速度接近O(1),效率更高:
program common_values_hash use iso_fortran_env use hash_map_int ! 注意:不同编译器的哈希模块可能不同,需对应调整 implicit none type(hash_map_type) :: value_map integer :: val, stat, u1, u2, u3 character(len=25) :: f1 = "input1.txt", f2 = "input2.txt", f3 = "common_output.txt" ! 把第一个文件的数值存入哈希集合 open(newunit=u1, file=f1, status="old", action="read") call value_map%init() do read(u1, *, iostat=stat) val if (stat /= 0) exit call value_map%put(val, .true.) ! 用数值当键,标记存在即可 end do close(u1) ! 遍历第二个文件,检查数值是否在集合中,写入结果 open(newunit=u2, file=f2, status="old", action="read") open(newunit=u3, file=f3, status="replace", action="write") do read(u2, *, iostat=stat) val if (stat /= 0) exit if (value_map%has_key(val)) then write(u3, *) val call value_map%remove(val) ! 避免重复写入同一个数值 end if end do close(u2) close(u3) call value_map%destroy() end program common_values_hash
关于你之前的问题
你说variable1(i)=variable2(j)无法正常工作,大概率是双重循环的逻辑没处理对。比如正确的基础循环写法应该是这样(虽然效率低,但逻辑没问题):
! 假设已经读取了variable1(n1)和variable2(n2) do i = 1, n1 do j = 1, n2 if (variable1(i) == variable2(j)) then write(u3, *) variable1(i) exit ! 找到匹配后跳出内层循环,避免重复写入同一个值 end if end do end do
不过这种方法在数组元素多的时候会很慢,所以更推荐前面两种高效方案。
内容的提问来源于stack exchange,提问作者guitae
相关产品推荐
相关产品推荐

