web-dev-qa-db-fra.com

Convertir une chaîne (sans séparateur) en liste

J'ai un numéro de téléphone (chaîne), par ex. "+ 123-456-7890", que je veux transformer en une liste qui ressemble à: [+, 1, 2, 3, -, ...., 0].

Pourquoi? Je peux donc parcourir la liste et supprimer tous les symboles, donc je me retrouve avec une liste de seuls chiffres, que je peux ensuite reconvertir en chaîne.

Quelle est la meilleure façon de résoudre ce problème? Aucune des solutions que j'ai rencontrées n'est applicable, car je n'ai pas de caractères spéciaux entre les chiffres (donc je ne peux pas diviser la chaîne ici.)

Des idées? J'apprécie vraiment cela!

Modifier - c'est ce que j'ai essayé:

x = row.translate(None, string.digits)
list = x.split()

Également:

filter(lambda x: x isdigit())
17
nv39

Vous voulez dire que vous voulez quelque chose comme:

''.join(n for n in phone_str if n.isdigit())

Cela utilise le fait que les chaînes sont itérables. Ils produisent 1 caractère à la fois lorsque vous les parcourez.


Concernant vos efforts,

Celui-ci en fait supprime tous les chiffres de la chaîne vous laissant uniquement des non-chiffres.

x = row.translate(None, string.digits)

Celui-ci fractionne la chaîne sur les séquences d'espaces, pas après chaque caractère:

list = x.split()
8
mgilson

Faites un list (your_string).

>>> s = "mep"
>>> list(s)
['m', 'e', 'p']
59
poitroae
''.join(filter(str.isdigit, "+123-456-7890"))
6
Kabie

Vous pouvez utiliser le module re:

import re
re.sub(r'\D', '', '+123-456-7890')

Cela remplacera tous les non-chiffres par ''.

4
tur1ng

Je sais que cette question a été répondue, mais juste pour souligner ce que timeit a à dire sur l'efficacité des solutions. En utilisant ces paramètres:

size = 30
s = [str(random.randint(0, 9)) for i in range(size)] + (size/3) * ['-']
random.shuffle(s)
s = ''.join(['+'] + s)
timec = 1000

C'est le "numéro de téléphone" a 30 chiffres, 1 plus chanter et 10 '-'. J'ai testé ces approches:

def justdigits(s):
    justdigitsres = ""
    for char in s:
        if char.isdigit():
            justdigitsres += str(char)
    return justdigitsres

re_compiled = re.compile(r'\D')

print('Filter: %ss' % timeit.Timer(lambda : ''.join(filter(str.isdigit, s))).timeit(timec))
print('GE: %ss' % timeit.Timer(lambda : ''.join(n for n in s if n.isdigit())).timeit(timec))
print('LC: %ss' % timeit.Timer(lambda : ''.join([n for n in s if n.isdigit()])).timeit(timec))
print('For loop: %ss' % timeit.Timer(lambda : justdigits(s)).timeit(timec))
print('RE: %ss' % timeit.Timer(lambda : re.sub(r'\D', '', s)).timeit(timec))
print('REC: %ss' % timeit.Timer(lambda : re_compiled.sub('', s)).timeit(timec))
print('Translate: %ss' % timeit.Timer(lambda : s.translate(None, '+-')).timeit(timec))

Et est sorti avec ces résultats:

Filter: 0.0145790576935s
GE: 0.0185861587524s
LC: 0.0151798725128s
For loop: 0.0242128372192s
RE: 0.0120108127594s
REC: 0.00868797302246s
Translate: 0.00118899345398s

Apparemment, les GE et les LC sont encore plus lents qu'une regex ou une regex compilée. Et apparemment, mon CPython 2.6.6 n'a pas beaucoup optimisé l'ajout de chaînes. translate semble être le plus rapide (ce qui est attendu car le problème est indiqué comme "ignorer ces deux symboles", plutôt que "obtenir ces chiffres" et je pense que c'est assez bas).

Et pour size = 100:

Filter: 0.0357120037079s
GE: 0.0465779304504s
LC: 0.0428011417389s
For loop: 0.0733139514923s
RE: 0.0213229656219s
REC: 0.0103371143341s
Translate: 0.000978946685791s

Et pour size = 1000:

Filter: 0.212141036987s
GE: 0.198996067047s
LC: 0.196880102158s
For loop: 0.365696907043s
RE: 0.0880808830261s
REC: 0.086804151535s
Translate: 0.00587010383606s
3
dmg

A python string is une liste de caractères. Vous pouvez le parcourir maintenant!

justdigits = ""
for char in string:
    if char.isdigit():
        justdigits += str(char)
2
uptownnickbrown

Au lieu de convertir en liste, vous pouvez simplement parcourir la première chaîne et créer une deuxième chaîne en ajoutant chacun des caractères numériques que vous trouvez à cette nouvelle chaîne.

2
Justin Ethier

Avez-vous essayé list (x) ??

 y = '+123-456-7890'
 c =list(y)
 c

['+', '1', '2', '3', '-', '4', '5', '6', '-', '7', '8', '9', ' 0 ']

1
Ajith

Vous pouvez utilisez str.translate, il suffit de lui donner les bons arguments:

>>> dels=''.join(chr(x) for x in range(256) if not chr(x).isdigit())
>>> '+1-617-555-1212'.translate(None, dels)
'16175551212'

N.b .: Cela ne fonctionnera pas avec les chaînes unicode en Python2, ou pas du tout en Python3. Pour ces environnements, vous pouvez créer une classe personnalisée à passer à unicode.translate:

>>> class C:
...    def __getitem__(self, i):
...       if unichr(i).isdigit():
...          return i
... 
>>> u'+1-617.555/1212'.translate(C())
u'16175551212'

Cela fonctionne également avec les chiffres non ASCII:

>>> print u'+\u00b9-\uff1617.555/1212'.translate(C()).encode('utf-8')
¹6175551212
0
Robᵩ