OVH Cloud OVH Cloud

comptage de caracteres specifique dans une chaine

22 réponses
Avatar
Eric Deveaud
bonjour,

je dispose de chaines de plusieur centaines de milliers de caracteres
parmis les caracteres de ces chaines certains sont des caracteres de padding
(un seul par type de chaine, généralement c'est le caractere *)

je dois à partir des chaines avec padding sortir les données suivantes

1) une liste des positions (indice) ou apparaissent ces caracteres de padding

2) une liste de la taille de la chaine d'origine avec comme valeur pour chaque
position le nombre de caracteres de padding rencontrés jsuqu'a cette position
incluse

exemple: sur une chaine de 15 de long

0 10 20
| |
padded_seq = "aaaaaa*aaaa*aaa"
^ ^
| |
6 11

je veux obtenir
padding_pos --> [6, 11]
padding_count --> [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2]


pour ce faire j'ai commis les bouts de code suivants


Option 1 je découpe en 2 taches individuelles

#determination des positions des caracteres de padding
def get_padding_pos(padded_str, padding_mark='*'):
res = []
start = 0
p = padded_str.find(padding_mark, start)
while p != -1:
res.append(p)
p = padded_str.find(padding_mark, start)
return res

# determination de la liste du nombre de padding_mark precedent une position
def get_padding_count(padded_str, padding_mark='*'):
padding_count = []
n = 0
start = 0
for end in padding_pos:
padding_count += [n]*(end-start)
start = end
n+=1

padding_count += [n]*(len(padded_seq)-start)

option 2 je fais les 2 d'un coup

def get_padded_spec(padded_seq, padding_mark='*'):
i = n = 0
stop = len(padded_seq)
padding_pos = []
padding_count = []
while i < stop:
if padded_seq[i] == padding_mark:
padding_pos.append(i)
n += 1
padding_count.append(n)
i += 1
return padding_pos, padding_count
je trouve ça très lourd comme traitement surtout sur des chaines de plusieurs
centaines de milliers de caracteres, avez vous mieux à me proposer ??

pour le momment je travaille sur des listes, je vais passer en array très
prochainement, y gagnerais-je en temps d'exécution (je sais j'ai qu'a mesurer)

Eric
--
- mais ce netbsd, c'est un linux ou pas ??
- NON ! C'est un Unix ! C'est un Unix-based et Linux est un Unix-like
- ok c bien ce ke je me disait, bon alors je recherche toujours un LINUX
-+- Dragondir in Guide du BSDiste pervers -+- Vous avez dit Nulix ? -+-

10 réponses

1 2 3
Avatar
Pierre Quentel
bonjour,

je dispose de chaines de plusieur centaines de milliers de caracteres
parmis les caracteres de ces chaines certains sont des caracteres de padding
(un seul par type de chaine, généralement c'est le caractere *)

je dois à partir des chaines avec padding sortir les données suivantes

1) une liste des positions (indice) ou apparaissent ces caracteres de padding

2) une liste de la taille de la chaine d'origine avec comme valeur pour chaque
position le nombre de caracteres de padding rencontrés jsuqu'a cette position
incluse

exemple: sur une chaine de 15 de long

0 10 20
| |
padded_seq = "aaaaaa*aaaa*aaa"
^ ^
| |
6 11

je veux obtenir
padding_pos --> [6, 11]
padding_count --> [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2]


Je ne sais pas si c'est mieux, mais tu peux utiliser enumerate :


s = "aaaaaa*aaaa*aaa"
padding = '*'
count = 0
positions = []
new_list = []
for i,x in enumerate(s):
if x == padding:
count += 1
positions.append(i)
new_list.append(count)


Pierre

Avatar
Gerard Flanagan
Eric Deveaud wrote:
bonjour,

je dispose de chaines de plusieur centaines de milliers de caracteres
parmis les caracteres de ces chaines certains sont des caracteres de padd ing
(un seul par type de chaine, généralement c'est le caractere *)

je dois à partir des chaines avec padding sortir les données suivantes

1) une liste des positions (indice) ou apparaissent ces caracteres de pad ding

2) une liste de la taille de la chaine d'origine avec comme valeur pour c haque
position le nombre de caracteres de padding rencontrés jsuqu'a cette po sition
incluse

exemple: sur une chaine de 15 de long

0 10 20
| |
padded_seq = "aaaaaa*aaaa*aaa"
^ ^
| |
6 11

je veux obtenir
padding_pos --> [6, 11]
padding_count --> [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2]




Comme le reponse de Pierre Quentel, mais "en 2 taches individuelles":

s = "aaaaaa*aaaa*aaa"

padding_pos = []
padding_count = []

for index, char in enumerate(s):
if char == '*':
padding_pos.append(index)

#'padding_pos' trouve, 'padding_count' peut etre construire
x = [0] + padding_pos + [len(s)]

for i in range(0, len(x)-1):
padding_count.extend( [i] * (x[i+1] - x[i]) )

Gerard

Avatar
Méta-MCI
Bonjour !

Comme c'est vendredi, je t'ai concocté un truc pas beau, tordu, trollesque,
mais qui marche :


def blabla(ch, marq, par):
global l #inutile, mais pour marquer la globalité de l
l.append(len(par))
if ch==marq:
return True

seq = "aaaaaa*aaaa*aaa"
marq="*"
l=[]
print [p for p,c in enumerate(seq) if blabla(c,marq,locals()['_[1]'])]
print l



Bonne lecture (Yerk ! Yerk ! Yerk !)

Michel Claveau
Avatar
pbouige
In article , Eric Deveaud wrote:

bonjour,

je dispose de chaines de plusieur centaines de milliers de caracteres
parmis les caracteres de ces chaines certains sont des caracteres de padding
(un seul par type de chaine, généralement c'est le caractere *)

je dois à partir des chaines avec padding sortir les données suivantes

1) une liste des positions (indice) ou apparaissent ces caracteres de padding

2) une liste de la taille de la chaine d'origine avec comme valeur pour chaque
position le nombre de caracteres de padding rencontrés jsuqu'a cette position
incluse

exemple: sur une chaine de 15 de long

0 10 20
| |
padded_seq = "aaaaaa*aaaa*aaa"
^ ^
| |
6 11

je veux obtenir
padding_pos --> [6, 11]
padding_count --> [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2]


pour la position celle-ci te va ?

padded_seq = "aaaaaa*aaaa*aaa"
[ index for index in range(len(padded_seq)) if padded_seq[index] == '*']
[6, 11]




padded_seq = "aa*a*a*aaaa*aa*"
[ index for index in range(len(padded_seq)) if padded_seq[index] == '*']
[2, 4, 6, 11, 14]




je cherche pour l'autre, Philippe ;-)



Avatar
Méta-MCI
Un peu plus court ;


def blabla(ch, marq, par):
l.append(len(par))
return ch==marq

seq = "aaaaaa*aaaa*aaa"
marq="*"
l=[]
print [p for p,c in enumerate(seq) if blabla(c,marq,locals()['_[1]'])]
print l
Avatar
Méta-MCI
Encore plus court :

seq = "aaaaaa*aaaa*aaa"
marq="*"
l=[]
print [p for p,c in enumerate(seq) if l.append(len(locals()['_[1]'])) or
(c==marq)]
print l
Avatar
erichuchet
Je pense que le probleme d'eric est surtout un probleme de vitesse, au
vu de la quantité de données à traiter. Je doute que la
compréhension list soit la bonne soulution.

Eric2
Avatar
Michel Claveau
Bonjour !

probleme de vitesse ... quantité à traiter ... doute que la
compréhension list soit la bonne soulution.


ça demande confirmation. Surtout que les listes en intention sont
réputées plutôt rapides.

--
@-salutations

Michel Claveau

Avatar
Méta-MCI
Re

Par exemple, pour une chaîne de 1,5 millions de caractères, contenant 200
000 marques, cela met 3,6 s sur mon Win-XP à 1,6 GHz.

Maintenant, si l'on veut aller plus vite, il faudrait, AMHA, remplacer
"append" par une initialisation préalable de "l" (dont on connaît la
longueur a priori), avec une affectation indicée.
Mais, est-ce bien nécessaire ?

@-salutations

Michel Claveau
Avatar
Eric Deveaud
Méta-MCI wrote:
Encore plus court :

seq = "aaaaaa*aaaa*aaa"
marq="*"
l=[]
print [p for p,c in enumerate(seq) if l.append(len(locals()['_[1]'])) or
(c==marq)]
print l


dans ce cas j'en reste à mon code initial
self.padding_pos = [i for i, c in enumerate(seq) if c == padding_mark]

mais j'ai des doutes sur la pertinance de ce code sur des chaines de grande
tailles

Eric

--
- Papa ! Papa ! PAAAAAAAAApppppppaaaaaaaaa !
- Oui Ben qu'est-ce-qu'il y a ?
- Y'a quelqu'un qui a touché à mon kernel !
+BL in Guide du Macounet Pervers : MOSXS est un long fleuve tranquille+

1 2 3