问题
I would like to know whether it is possible to have a function that erases all of the 2D repeated nodes from an array, i.e.:
A(xy,1:2)
A(xy,1) = /1,2,4,5,5,9,6,8,2,5,4/
A(xy,2) = /5,2,5,6,7,6,6,3,7,6,6/
After
A(xy,1) = /1,2,4,5,5,9,6,8,2,4/
A(xy,2) = /5,2,5,6,7,6,6,3,7,6/
When I try to execute @HighPerformanceMark's code in a blank program, there are several compiling errors that I do not get:
repeating.f90:24.20:
mask(ix) = NOT(ANY(arraya(1,:ix-1)==arraya(1,ix).AND.&
1
Error: 'i' argument of 'not' intrinsic at (1) must be INTEGER
repeating.f90:29.11:
ALLOCATE(index_vector, source=PACK([(ix, ix=1,numcols) ],mask))
1
Error: Array specification required in ALLOCATE statement at (1)
repeating.f90:32.11:
...
What can you say about this?
回答1:
Yes, here's one way of doing what you want. Note that this will copy the unique elements of array A into a new array called B rather than resize A on the fly. I've called the arrays arraya
and arrayb
because 1-character names go against my coding standards.
PROGRAM test
USE iso_fortran_env
IMPLICIT NONE
INTEGER, PARAMETER :: numrows = 2
INTEGER, PARAMETER :: numcols = 11
INTEGER, DIMENSION(numrows,numcols) :: arraya
LOGICAL, DIMENSION(:), ALLOCATABLE :: mask
INTEGER, DIMENSION(:,:), ALLOCATABLE :: arrayb
INTEGER :: ix
INTEGER, DIMENSION(:), ALLOCATABLE :: index_vector
arraya(1,:) = [1,2,4,5,5,9,6,8,2,5,4]
arraya(2,:) = [5,2,5,6,7,6,6,3,7,6,6]
! First, find the duplicate elements
ALLOCATE(mask(numcols))
mask = .TRUE.
DO ix = numcols,2,-1
mask(ix) = .NOT.(ANY(arraya(1,:ix-1)==arraya(1,ix).AND.&
arraya(2,:ix-1)==arraya(2,ix)))
END DO
! Make an index vector
ALLOCATE(index_vector, source=PACK([(ix, ix=1,numcols) ],mask))
! Now copy the unique elements of a into b
ALLOCATE(arrayb, source=arraya(:,index_vector))
END PROGRAM test
Note also:
- I've written this as a program, you might want to rewrite it into a function which returns what I've called
arrayb
. - There's no error checking or any of that sort of stuff, this is not production-ready code.
- You could probably dispense with
index_vector
and rewrite the last statement like thisALLOCATE(arrayb, source=arraya(:,PACK([(ix, ix=1,numcols) ],mask)))
but (a) that's a wee bit cryptic and (b) I haven't tested it. - I've only tested this on your input data and a few minor variations.
- This keeps the first (leftmost) instance of duplicated elements.
来源:https://stackoverflow.com/questions/14137610/remove-repeated-elements-in-a-2d-array-in-fortran