У меня есть строки, содержащие числа с их единицами, например, 2 ГБ, 17 футов, и т.д. Я хотел бы разделить число от единицы и создать 2 различных строки. Иногда, существует пробел между ними (например, 2 ГБ), и легко сделать это с помощью разделения ('').
Когда они вместе (например, 2 ГБ), я протестировал бы каждый символ, пока я не нахожу букву вместо числа.
s='17GB'
number=''
unit=''
for c in s:
if c.isdigit():
number+=c
else:
unit+=c
Существует ли лучший способ сделать это?
Спасибо
s='17GB'
for i,c in enumerate(s):
if not c.isdigit():
break
number=int(s[:i])
unit=s[i:]
Вы можете выйти из цикла, когда найдете первый нецифровой символ
for i,c in enumerate(s):
if not c.isdigit():
break
number = s[:i]
unit = s[i:].lstrip()
Если у вас есть отрицательные и десятичные числа:
numeric = '0123456789-.'
for i,c in enumerate(s):
if c not in numeric:
break
number = s[:i]
unit = s[i:].lstrip()
tokenize
может помочь:
>>> import StringIO
>>> s = StringIO.StringIO('27GB')
>>> for token in tokenize.generate_tokens(s.readline):
... print token
...
(2, '27', (1, 0), (1, 2), '27GB')
(1, 'GB', (1, 2), (1, 4), '27GB')
(0, '', (2, 0), (2, 0), '')
Для этой задачи я бы определенно использовал регулярное выражение:
import re
there = re.compile(r'\s*(\d+)\s*(\S+)')
thematch = there.match(s)
if thematch:
number, unit = thematch.groups()
else:
raise ValueError('String %r not in the expected format' % s)
В шаблоне RE, \s
означает "пробел", \d
означает "цифра", \S
означает не пробел; *
означает "0 или более из предыдущего", +
означает "1 или более из предыдущего, а круглые скобки заключают "группы захвата", которые затем возвращаются вызовом groups()
на объекте совпадения. (thematch
равен None, если заданная строка не соответствует шаблону: необязательный пробел, затем одна или несколько цифр, затем необязательный пробел, затем один или несколько не пробельных символов).
Вы можете использовать регулярное выражение для разделения строки на группы:
>>> import re
>>> p = re.compile('(\d+)\s*(\w+)')
>>> p.match('2GB').groups()
('2', 'GB')
>>> p.match('17 ft').groups()
('17', 'ft')
>>> s="17GB"
>>> ind=map(str.isalpha,s).index(True)
>>> num,suffix=s[:ind],s[ind:]
>>> print num+":"+suffix
17:GB
Регулярное выражение.
import re
m = re.match(r'\s*(?P<n>[-+]?[.0-9])\s*(?P<u>.*)', s)
if m is None:
raise ValueError("not a number with units")
number = m.group("n")
unit = m.group("u")
Оно даст вам число (целое или с фиксированной точкой; слишком трудно отличить "e" в научной нотации от префикса единицы) с необязательным знаком, за которым следуют единицы, с необязательным пробелом.
Вы можете использовать re.compile()
, если собираетесь делать много совпадений.
Вы должны использовать регулярные выражения, группируя вместе то, что вы хотите выяснить:
import re
s = "17GB"
match = re.match(r"^([1-9][0-9]*)\s*(GB|MB|KB|B)$", s)
if match:
print "Number: %d, unit: %s" % (int(match.group(1)), match.group(2))
Измените regex в соответствии с тем, что вы хотите разобрать. Если вы не знакомы с регулярными выражениями, вот отличный обучающий сайт.