Удалить повторяющиеся строки в Fortran77
У меня есть файл, который представляет собой таблицу из 119 столбцов (разделенных пробелами) и около 50000 строк (строк). Я хотел бы удалить дублированные записи, то есть те строки, которые имеют все идентичные столбцы (119). Я набросал этот код:
PROGRAM deldup
IMPLICIT NONE
DOUBLE PRECISION PAR(119),PAR2(119)
INTEGER I,J,K,LINE,TREP
CHARACTER filename*40
c Get the input file name
CALL getarg(1,filename)
c File where the results will be stored.
OPEN(29, FILE="result.dat", STATUS='UNKNOWN')
c Current line number
LINE=0
c counting repeated points
TREP=0
101 LINE=LINE+1
OPEN(27, FILE=filename, STATUS='OLD')
c Verifying that we are not in the first line... and we read the
c corresponding one
IF (LINE.NE.1) THEN
DO K=1,LINE-1
READ(27,11,ERR=103,END=9999)
END DO
ENDIF
READ(27,11,ERR=103,END=9999) (PAR(I),I=1,119)
c Start comparing line by line looking for matches. If a match is
c found , close the
c file and open it again to read the next line. If the end of file is
c reached and not iqual rows found, write the line in "results.dat"
102 READ(27, 11,END=104, ERR=102) (PAR2(I),I=1,119)
DO J=1,119
IF ( PAR(J).NE.PAR2(J) ) THEN
GOTO 102
ELSEIF (J.EQ.119) THEN
TREP=TREP+1
GOTO 103
ENDIF
END DO
104 WRITE(29,11) (PAR(I),I=1,119)
103 CLOSE(27)
GOTO 101
9999 WRITE(*,*) "DONE!,", TREP, "duplicated points found!"
CLOSE(27)
CLOSE(28)
CLOSE(29)
11 FORMAT(200E14.6)
END
который на самом деле работает, это просто супер медленно. Зачем? Есть ли библиотека, которую я могу использовать? Извините за мое невежество, я совершенно новый с Fortran77.
2 ответа
Для каждой строки вы открываете и закрываете исходный файл, что очень медленно! Чтобы ускорить процесс, вы можете просто использовать rewind
,
Однако основная проблема заключается в сложности вашего алгоритма: O(n^2)
Вы сравниваете каждую строку с каждой другой строкой. Для начала я бы сохранил список уникальных строк и сравнил их с этим списком. Если новая строка уже указана, отмените ее, если нет - это новая уникальная строка. Это уменьшит сложность до O(n*m)
с (надеюсь) m << n
(m - количество уникальных строк). Сортировка строк, вероятно, ускорит сравнение.
Следующим замечанием будет переход от ввода / вывода к памяти! Чтение полного файла в массив или, по крайней мере, сохранение списка уникальных строк в памяти. Массив двойной точности 50 000x119 требует ~45 МБ ОЗУ, поэтому я думаю, что это должно быть выполнимо;-) Запишите результат обратно одним куском на последнем этапе.
Первый вопрос: зачем придерживаться Fortran 77? С появлением g95 и gfortran нет никаких реальных причин использовать стандарт, который устарел уже более двадцати лет.
Канонический способ удалить дубликаты - это отсортировать их, удалить дубликаты, а затем вывести их в исходном порядке. Если вы используете хороший алгоритм сортировки, такой как быстрая сортировка или heapsort, это даст вам производительность O(n log n).
Еще одно замечание: также неплохо было бы добавлять магические числа, такие как 119, в вашу программу в операторы PARAMETER.