파일의 각 줄에 하나 이상의 값이 존재하는 최소 값 집합을 찾습니다.

파일의 각 줄에 하나 이상의 값이 존재하는 최소 값 집합을 찾습니다.

다음과 같은 파일이 있습니다 df.

1   4
1   6
1   7
1   10
2   3
2   9
2   10
3   4
4   7
9   10

df의 각 행에 이러한 값 중 적어도 하나가 포함되도록 가장 작은 값 집합을 결정해야 합니다.

위에서 df기대하는 바는 out다음과 같습니다.

1
2
4
9

작동하는 프로세스가 있지만 매우 느립니다. 이 작업을 더 빠르게 수행하거나 프로세스를 병렬화할 수 있는 방법이 있습니까?

x=1  
while [ $x -gt 0 ]  
do  
    i=$(paste df | tr '\t' '\n' | sort | uniq -c | 
        sort -r -k1,1 -k2,2n | awk 'NR==1{print $2}')  
    echo $i >> out  
    grep -vw $i df > tmpdf  
    cat tmpdf > df  
    x=$(paste df | wc -l)  
done

답변1

다음은 "라인 노이즈" Perl입니다.

perl -lane '
        for $f (@F) {push @{$x{$f}}, $.}                          # 1.
    } END {
        use List::Util qw/any first/;
        sub sort_by_count_desc {
            map  { $_->[0] } 
            sort { $b->[1] <=> $a->[1] || $a->[0] <=> $b->[0] } 
            map  { [$_, scalar(@{$x{$_}})] } 
            @_ 
        }
        @ordered = sort_by_count_desc(keys %x);                   # 2.
        %result = ();
        for ($i=1; $i<=$.; $i++) {                                # 3.
            $node = first { any {$_ == $i} @{$x{$_}} } @ordered;  # 4.
            $result{$node} = 1;
        }
        print join "\n", sort_by_count_desc(keys %result);
' df

어디

  1. 파일의 행을 반복하고 각 값을 해당 값이 나타나는 행 목록에 매핑합니다.
  2. 모양 목록 크기에 따라 내림차순으로 정렬된 값의 정렬된 행을 생성합니다.
  3. 줄 번호 범위와 foreach 줄 번호를 반복합니다.
  4. 행 번호가 나타나는 첫 번째 값 찾기

이 출력

1
2
4
10

답변2

이건 "멍청이"리눅스최적화에 사용 bash하지만 특별히 이식성이 없으며 알고리즘을 개선하지 않습니다.

f=$(mktemp) ; cp df $f
while [ -s $f ]  ; do   
    tr '\t' '\n' < $f | sort | uniq -c | sort -r -k1,1 -k2,2n | 
    grep -om1 '\S$' | tee >(grep -vwf - $f | sponge $f)
done
rm $f

노트:

  • 사용df입력 파일을 스크래치 패드로 사용하는 것은 좋지 않습니다 mktemp. 대신 이것을 사용하십시오.

  • 출력은 다음과 같습니다.표준 출력. 필요한 경우 로 변경합니다 done.done > out

  • 이것spongeutil에는 더 이상 이름을 지정할 필요가 없습니다.tmpdf문서.

  • 검색 문자열 변수 대신 tee및를 사용합니다 .grep -f -$i

  • wc -l있는지 확인해보세요0충분하지 않습니다 test -s.

관련 정보