OVH Cloud OVH Cloud

supprimer doublon dans un tableau

6 réponses
Avatar
lepetitjoe
Salut
j=B4ai dans mon tableau les donn=E9es suivantes par exemple:

44.55.555.55 30.11.12.11.0 wwwww suitecaracteres1
11.122.11.10 30.11.12.11.0 xxxxxx suitecaracteres2
55.122.11.10 30.11.12.11.0 bbbbbb suitecaracteres3
77.122.11.10 30.11.12.11.0 ssssss suitecaracteres4
50.122.11.10 30.11.12.11.0 aaaaaa suitecaracteres5
666.122.11.10 30.11.12.11.0 kkkkkk suitecaracteres6
666.122.11.10 30.11.12.11.0 kkkkkk suitecaracteres6 ???
222.122.11.10 30.11.12.11.0 uuuuuu suitecaracteres7
111.122.11.10 30.11.12.11.0 lllllll suitecaracteres8
365.122.11.10 30.11.12.11.0 ppppp suitecaracteres9

Je voudrai supprimer la ligne " 666.122.11.10 30.11.12.11.0 kkkkkk
suitecaracteres6 " qui est identique =E0 celle qui la suit
directement apres =E0 la seule difference que celle qui la suit =E0 3
points d=B4interrogations a sa fin ( ??? ).
Il en existe comme ca d=B4autres doublons dont la deuxieme ligne
identique =E1 tjrs ces ??? =E0 la fin.
Comment proceder?

Merci a bientot

6 réponses

Avatar
ctobini
Hello,

C'est à dire 'dans ton tableau' ? Quel type de tabeau as-tu utilisé,
un tableau $tab = [], @tab = (), %h = ()... ?

Si tes données sont d'abord sous cette forme dans un fichier, tu peux
passer par un tableau de hashage :

my %h; # déclare un tableau de hash

while(<>) {
my @tab_temp = split ' ';
a ce moment tu auras par exemple :
$tab[0] = 666.122.11.10
$tab[1] = 30.11.12.11.0
$tab[2] = kkkkkk
$tab[3] = suitecaracteres6
ensuite passer par le hashage :
$h{$tab[0]}{$tab[1]}{$tab[2]}{$tab[3]} = undef;
de cette manière les doublons seront supprimés dans le %h même
}

Il ne te reste plus qu'à réécrire les données de ton hash :

foreach my $k(keys %h) {
foreach my $k2 (keys %{$h{$k}}) {
foreach my $k3(keys %{$h{$k}{$k2}}) {
foreach my $k4(keys %{$h{$k}{$k2}{$k3}}) {
print "$k $k2 $k3 $k4n"
}
}
}
}

Regarde du côté du CPAN, il y a peut-être des modules faisant déj à
ça directement à partir d'un tableau.

C. Tobini
Avatar
scottalorda

Hello,

C'est à dire 'dans ton tableau' ? Quel type de tabeau as-tu utilisé,
un tableau $tab = [], @tab = (), %h = ()... ?

Si tes données sont d'abord sous cette forme dans un fichier, tu peux
passer par un tableau de hashage :

my %h; # déclare un tableau de hash

while(<>) {
my @tab_temp = split ' ';
a ce moment tu auras par exemple :
$tab[0] = 666.122.11.10
$tab[1] = 30.11.12.11.0
$tab[2] = kkkkkk
$tab[3] = suitecaracteres6
ensuite passer par le hashage :
$h{$tab[0]}{$tab[1]}{$tab[2]}{$tab[3]} = undef;
de cette manière les doublons seront supprimés dans le %h même
}

Il ne te reste plus qu'à réécrire les données de ton hash :

foreach my $k(keys %h) {
foreach my $k2 (keys %{$h{$k}}) {
foreach my $k3(keys %{$h{$k}{$k2}}) {
foreach my $k4(keys %{$h{$k}{$k2}{$k3}}) {
print "$k $k2 $k3 $k4n"
}
}
}
}

Regarde du côté du CPAN, il y a peut-être des modules faisant déj à
ça directement à partir d'un tableau.

C. Tobini
Salut,


Un peu compliqué de tout parser dans un hachage multiple.
D'après ce que j'ai compris, l'index semble n'être que sur le premier
champ.
Pas la peine donc de tout décortiquer.
D'autant que parser par un ' ' peut engendrer des décalages si un
champ en contient.
On peut donc, pourquoi pas, ne prendre que le premier champ en guise
d'index, et la totalité de la ligne comme valeur.

Si on veut garder la première occurence de chaque index :
while my $ligne(<>) {
my $index = (split / /,$ligne)[0];
$h{$index} = $ligne unless (exists $h{$index});
}

ou bien si on veut garder la dernière:
while my $ligne (<>) {
my $index = (split / /,$ligne)[0];
$h{$index} = $ligne;
}

Ensuire pour reconstituer, un simple:
foreach my $clef (keys %h){
print "$valeurn";
}
suffira.

J'espère que cela aidera.

Sébastien

Avatar
ctobini
Bonjour,


ou bien si on veut garder la dernière:
while my $ligne (<>) {
my $index = (split / /,$ligne)[0];
$h{$index} = $ligne;
}


my $index = (split / /,$ligne)[3] pour la dernière ?

Pour l'indexation multiple, e suis parti du principe que les 4 champs
doivent être identiques pour avoir une ligne identique.

On aurait peut-être pu faire dans cet optique :

while(<>) {
s/s+/s/g; # juste pour éliminer les espaces multiples
$h{$&} = undef if /[0-9.]+s[0-9.]+s[A-Za-z]+s[A-Za-z0-9]+/
}

Je ne comprends pas pourquoi tu indexes la première chaine de la ligne
pour lui attribuer la valeur de la ligne entière. Autant indexer la
ligne entière sur les 4 champs pour être certain d'avoir une ligne
unique et pouvoir ensuite utiliser 'exists' pour voir l'existence de la
ligne entière.

Je ne suis pas spécialiste mais je crois que $h{quelque_chose} unless
exists $h{quelque_chose} ne sert pas à grand chose puisque la clé ne
peut être qu'unique (à confirmer ?).

C. Tobini

Avatar
Sébastien Cottalorda

Bonjour,


ou bien si on veut garder la dernière:
while my $ligne (<>) {
my $index = (split / /,$ligne)[0];
$h{$index} = $ligne;
}


my $index = (split / /,$ligne)[3] pour la dernière ?


Désolé, je me suis mal exprimé, le dernière *occurrence* vue pour
chaque index.

Pour l'indexation multiple, e suis parti du principe que les 4 champs
doivent être identiques pour avoir une ligne identique.


Pourquoi pas.

On aurait peut-être pu faire dans cet optique :

while(<>) {
s/s+/s/g; # juste pour éliminer les espaces multiples
$h{$&} = undef if /[0-9.]+s[0-9.]+s[A-Za-z]+s[A-Za-z0-9]+/
}

Je ne comprends pas pourquoi tu indexes la première chaine de la ligne
pour lui attribuer la valeur de la ligne entière. Autant indexer la
ligne entière sur les 4 champs pour être certain d'avoir une ligne
unique et pouvoir ensuite utiliser 'exists' pour voir l'existence de la
ligne entière.


Il m'a semblé toutefois que la pertinence de la ligne était sur le
premier champ et non sur les autres, c'est pourquoi mon index portait
uniquement sur le premier.
La compréhension du mécanisme index <-> stockage dans un hash n'en
était que plus facile (à mon avis).
L'auteur avait alors tout loisir d'adapter son index de pertinence à
sa guise.

D'autant que je lui fournissais également la piste de ne stocker que
la première ou la dernière des occurrences de chacuns de ses indexes.

Du coup, pourquoi ne pas créer l'index avec un substr ? .... tout est
permi dans ce cas de figure.
Je pense que l'on n'a pas assez d'éléments de la part de l'auteur du
message initial pour trancher.
Je ne propose qu'une solution parmi plusieurs possibles.

Je ne suis pas spécialiste mais je crois que $h{quelque_chose} unless
exists $h{quelque_chose} ne sert pas à grand chose puisque la clé ne
peut être qu'unique (à confirmer ?).

C. Tobini


Je ne suis pas d'accord,

$h{quelquechose} = .... unless (exists $h{quelquechose});
ne sert à conserver que la *première* occurence de l'index, c'est à
dire la première fois qu'on le voit (et uniquement celle là),
empêchant l'enregistrement des autres valeurs possibles pour cet index
(gràce au unless exists).

Sébastien


Avatar
Pierrick LE GALL
Bonjour,

Je propose une alternative aux propositions qui ont été faites dans ce
fil de discussion. Les autres solutions stockaient les lignes avant de
les afficher. Ce n'est pas idéal si la liste de lignes en entrée en
volumineuse.

Je propose plutôt d'itérer sur toute les lignes et de sauter les lignes
dont la clef a déjà été rencontrée.

my %keys = ();

while () {
my @fields = split /s+/, $_;

# si ma clef est constituée des 3 premières colonnes
next if (++$keys{$fields[0]}{$fields[1]}{$fields[2]} > 1);

# ici, tu fais ce que tu veux avec ta ligne
}

@+

--
Pierrick LE GALL
http://le-gall.net/pierrick
ingénieur R&D chez Talend, Open Data Solutions
Avatar
lepetitjoe
merci pour vos contribution, je teste cela tres tot ce matin car il est
1h du mat la , je vous donne la suite en journee
Merci encore de vos eclairages pertinents ...



schrieb:

Salut
j´ai dans mon tableau les données suivantes par exemple:

44.55.555.55 30.11.12.11.0 wwwww suitecaracteres1
11.122.11.10 30.11.12.11.0 xxxxxx suitecaracteres2
55.122.11.10 30.11.12.11.0 bbbbbb suitecaracteres3
77.122.11.10 30.11.12.11.0 ssssss suitecaracteres4
50.122.11.10 30.11.12.11.0 aaaaaa suitecaracteres5
666.122.11.10 30.11.12.11.0 kkkkkk suitecaracteres6
666.122.11.10 30.11.12.11.0 kkkkkk suitecaracteres6 ???
222.122.11.10 30.11.12.11.0 uuuuuu suitecaracteres7
111.122.11.10 30.11.12.11.0 lllllll suitecaracteres8
365.122.11.10 30.11.12.11.0 ppppp suitecaracteres9

Je voudrai supprimer la ligne " 666.122.11.10 30.11.12.11.0 kkkkkk
suitecaracteres6 " qui est identique à celle qui la suit
directement apres à la seule difference que celle qui la suit à 3
points d´interrogations a sa fin ( ??? ).
Il en existe comme ca d´autres doublons dont la deuxieme ligne
identique á tjrs ces ??? à la fin.
Comment proceder?

Merci a bientot