obtém valores que ocorrem apenas uma vez em um vetor

0

Existe um vetor de números que tenho em ordem crescente (é chamado t8 _)

2 7 8 9 11 15 34 91 91 92 94

O problema é que alguns números acontecem duas vezes. Eu não quero removê-los, mas eles precisam se tornar dois números distintos e não ponto flutuante. Eu pensei primeiro em percorrer o vetor:

which(duplicated(t8)) - that would be 9 and then go on 

t8[which(duplicated(t8))]<-t8[which(duplicated(t8))]+1

O próximo vetor seria

2 7 8 9 11 15 34 91 92 92 94

Repetindo o mesmo processo:

which(duplicated(t8)) - that would be 10 and the go on 

t8[which(duplicated(t8))]<-t8[which(duplicated(t8))]+1

quando o vetor seria

 2 7 8 9 11 15 34 91 92 993 94

Eu tentei sort -u e sort -nu (eles não funcionam).

Existe uma maneira perl ou python de fazer isso de forma interativa ... até que nenhum número duplicado esteja presente?

Eu gostaria de fazer isso com um arquivo para colocar na função ... editar ...

A resposta não está funcionando com o meu arquivo vetorial: link

    
por hjkefl 29.06.2015 / 17:17

2 respostas

1

O script a seguir lê um vetor de inteiros de cada linha de stdin.

#!/bin/bash

while read -a vec; do
        # INT_MIN for bash: 32-bit bash also supports 64-bit integers.
        min=$((-1<<63)) 
        for ((i = 0; i < ${#vec[@]}; i++)); do
                (( min = vec[i] = vec[i] > min ? vec[i] : min + 1 ))
        done
        echo "${vec[@]}"
done

Exemplo de entrada:

2 7 8 9 11 15 34 91 91 92 94
1 1 1 1 1 1 1 1 1 1
91 91 91
-1000 -900 -100 -100 -100 0 0 0
5 4 3 2 1 0
 1      1  1 1 1 

Exemplo de saída:

$ ./script.sh < input.txt 
2 7 8 9 11 15 34 91 92 93 94
1 2 3 4 5 6 7 8 9 10
91 92 93
-1000 -900 -100 -99 -98 0 1 2
5 6 7 8 9 10
1 2 3 4 5

Deixe-me saber se a saída não é como você esperava ou queria.

Atualizado: Esta versão processaria todos os inteiros em todas as linhas do stdin como uma entrada, não linha a linha. Seria capaz de aceitar linhas de comprimento arbitrário.

#!/bin/sh

min=$((-1<<63))

tr -s '[:space:]' '\n' |
while read val; do
        case ${val#[-+]} in
                ''|*[!0-9]*) continue ;;
        esac
        min=$((val > min ? val : min + 1))
        echo $min
done |
paste -s -d' ' -

Sessão de amostra:

$ echo -e '2 7 8 9 11 15 34 91 91 92 94' | ./script.sh
2 7 8 9 11 15 34 91 92 93 94
$ echo -e '91 91 91' | ./script.sh
91 92 93
$ echo -e '5 4 3 2 1 0' | ./script.sh
5 6 7 8 9 10
$ echo -e '-1000 -900 -100 -100 -100 0 0 0 +100 +100 +100' | ./script.sh
-1000 -900 -100 -99 -98 0 1 2 100 101 102
$ echo -e ' 1 1\n 1\n 1 \n1 \n1 ' | ./script.sh
1 2 3 4 5 6
$ echo -e 'a 1 b 2 3 c' | ./script.sh
1 2 3
    
por 29.06.2015 / 17:38
0

Talvez seja isso que você precisa:

#!usr/bin/perl                                                                                                                                                
use strict;
use warnings;

my@list=qw(2 7 8 9 11 15 34 91 91 92 94);
my%hash;


print "Input:\n@list\n";

foreach(@list)
{
    #count occurences for each element                                                                                                                        
    $hash{$_}++;
}

foreach my$key (keys %hash)
{
    TURN: while($hash{$key}>1)
    {
    #add a number between 1 and 10 to the duplicated value if                                                                                             
    #this value does not already exist                                                                                                                    
        for(my$i=1;$i<=10;$i++)
        {
            if(exists $hash{$key+$i})
            {
                next;
            }
            else
            {
                $hash{$key}--;
                $hash{$key+$i}=1;
                next TURN;
            }
        }
    }
}

my@result=sort{$a<=>$b}(keys %hash);

print "Result:\n@result\n";

Esse código conta as ocorrências de cada elemento e adiciona um número entre 1 e 10 ao valor para obter um que já não existe.

    
por 22.07.2015 / 16:45