Python에서 문자열의 단위에서 숫자 구분
나는 2GB, 17ft 등과 같은 단위의 숫자가 포함된 문자열을 가지고 있다. 나는 유닛에서 번호를 분리하여 두 개의 다른 문자열을 만들고 싶다. 때때로, 그것들 사이에 빈 공간(예: 2GB)이 있고 분할('' ')을 사용하여 그것을 하는 것은 쉽다.
그들이 함께 있을 때(예: 2GB), 나는 숫자 대신에 글자를 찾을 때까지 모든 문자를 테스트했다.
s='17GB'
number=''
unit=''
for c in s:
if c.isdigit():
number+=c
else:
unit+=c
더 좋은 방법이 있을까요?
감사해요.
정규식을 사용하여 문자열을 그룹으로 나눌 수 있습니다:
>>> import re
>>> p = re.compile('(\d+)\s*(\w+)')
>>> p.match('2GB').groups()
('2', 'GB')
>>> p.match('17 ft').groups()
('17', 'ft')
정규 표현을 사용하는 것은 어떨까요
http://python.org/doc/1.6/lib/module-regsub.html
정규식을 사용하여 확인할 내용을 그룹화해야 합니다:
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))
구문 분석할 내용에 따라 정규식을 변경합니다. 정규 표현이 익숙하지 않다면 훌륭한 튜토리얼 사이트입니다.
도움이 될 수 있음:
>>> 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 패턴에서, "흰색 공간"을 의미하고, "자리"를 의미하며, 공백이 아닌 공간을 의미하며, "앞의 0 이상"을 의미하고, "앞의 1 이상"을 의미하며, 괄호는 일치 객체에 대한 호출에 의해 반환되는 "캡처 그룹"을 포함한다. (지정된 문자열이 패턴과 일치하지 않는 경우 없음, 즉 선택적 공백, 한 자리 이상의 숫자, 선택적 공백, 한 자리 이상의 공백 문자입니다.
정규 표현.
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"와 단위 접두사를 구별하기에는 너무 어렵다)를 제공하고, 그 뒤에 단위와 공백을 선택적으로 제공한다.
경기를 많이 하실 분들은 이용하시면 됩니다.
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()
>>> s="17GB"
>>> ind=map(str.isalpha,s).index(True)
>>> num,suffix=s[:ind],s[ind:]
>>> print num+":"+suffix
17:GB
이것은 정규식보다 조금 더 관대해야 하는 접근법을 사용한다. 참고: 이는 게시된 다른 솔루션보다 성능이 좋지 않습니다.
def split_units(value):
"""
>>> split_units("2GB")
(2.0, 'GB')
>>> split_units("17 ft")
(17.0, 'ft')
>>> split_units(" 3.4e-27 frobnitzem ")
(3.4e-27, 'frobnitzem')
>>> split_units("9001")
(9001.0, '')
>>> split_units("spam sandwhiches")
(0, 'spam sandwhiches')
>>> split_units("")
(0, '')
"""
units = ""
number = 0
while value:
try:
number = float(value)
break
except ValueError:
units = value[-1:] + units
value = value[:-1]
return number, units.strip()
과학적 표기법 이 정규식은 과학적 표기법에 있을 수 있는 숫자를 구문 분석하는 데 잘 작동하며 scanf에 대한 최근 파이썬 문서를 기반으로 합니다:
units_pattern = re.compile("([-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?|\s*[a-zA-Z]+\s*$)")
number_with_units = list(match.group(0) for match in units_pattern.finditer("+2.0e-1 mm"))
print(number_with_units)
>>>['+2.0e-1', ' mm']
n, u = number_with_units
print(float(n), u.strip())
>>>0.2 mm
아래 정규식 패턴을 사용해 보십시오. 첫 번째 그룹(어떤 방식으로든 번호에 대한 scanf() 토큰)은 remodule에 대한 python 문서에서 직접 들어옵니다.
import re
SCANF_MEASUREMENT = re.compile(
r'''( # group match like scanf() token %e, %E, %f, %g
[-+]? # +/- or nothing for positive
(\d+(\.\d*)?|\.\d+) # match numbers: 1, 1., 1.1, .1
([eE][-+]?\d+)? # scientific notation: e(+/-)2 (*10^2)
)
(\s*) # separator: white space or nothing
( # unit of measure: like GB. also works for no units
\S*)''', re.VERBOSE)
'''
:var SCANF_MEASUREMENT:
regular expression object that will match a measurement
**measurement** is the value of a quantity of something. most complicated example::
-666.6e-100 units
'''
def parse_measurement(value_sep_units):
measurement = re.match(SCANF_MEASUREMENT, value_sep_units)
try:
value = float(measurement[0])
except ValueError:
print 'doesn't start with a number', value_sep_units
units = measurement[5]
return value, units
이러한 종류의 파서는 이미 다음에 통합되어 있습니다:
핀트(Pint)는 물리량(숫자 값과 측정 단위의 곱)을 정의, 작동 및 조작하기 위한 파이썬 패키지이다. 그것은 그것들 사이의 산술 연산과 다른 단위와의 변환을 허용한다.
와 함께 설치할 수 있습니다.
그런 다음 문자열을 구문 분석하고 원하는 값('규모')과 해당 단위를 얻을 수 있습니다:
>>> from pint import UnitRegistry
>>> ureg = UnitRegistry()
>>> size = ureg('2GB')
>>> size.m
2
>>> size.u
<Unit('gigabyte')>
>>> size.to('GiB')
<Quantity(1.86264515, 'gibibyte')>
>>> length = ureg('17ft')
>>> length.m
17
>>> length.u
<Unit('foot')>
>>> length.to('cm')
<Quantity(518.16, 'centimeter')>
불행하게도, 이전 코드들 중 어떤 것도 내 상황에서 제대로 작동하지 않았다. 나는 다음과 같은 코드를 개발했다. 코드 뒤의 아이디어는 모든 숫자가 숫자나 점으로 끝나는 것이다.
def splitValUnit(s):
s = s.replace(' ', '')
lastIndex = len(s) - 1
i = lastIndex
for i in range(lastIndex, -1, -1):
if (s[i].isdigit() or s[i] == '.'):
break
i = i + 1
value = 0
unit = ''
try:
value = float(s[:i])
unit = s[i:]
except:
pass
return {'value': value, 'unit': unit}
print(splitValUnit('7')) #{'value': 7.0, 'unit': ''}
print(splitValUnit('+7')) #{'value': 7.0, 'unit': ''}
print(splitValUnit('7m')) #{'value': 7.0, 'unit': 'm'}
print(splitValUnit('27')) #{'value': 27.0, 'unit': ''}
print(splitValUnit('7.')) #{'value': 7.0, 'unit': ''}
print(splitValUnit('2GHz')) #{'value': 2.0, 'unit': 'GHz'}
print(splitValUnit('+2.e-10H')) #{'value': 2e-10, 'unit': 'H'}
print(splitValUnit('2.3e+4 MegaOhm'))#{'value': 23000.0, 'unit': 'MegaOhm'}
print(splitValUnit('-4.')) #{'value': -4.0, 'unit': ''}
print(splitValUnit('e mm')) #{'value': 0, 'unit': ''}
print(splitValUnit('')) #{'value': 0, 'unit': ''}
'개발하자' 카테고리의 다른 글
테라폼과 함께 GCP 클라우드를 사용할 때 API를 자동으로 활성화할 수 있습니까? (0) | 2023.04.15 |
---|---|
FastAPI를 사용하여 요청에 헤더가 없을 때 사용자 지정 응답을 반환하는 방법은 무엇입니까? (0) | 2023.04.14 |
글로벌 '예외'를 빠른 속도로 포착API (0) | 2023.04.13 |
os.startfile(), Python 3.6을 사용하여 연 파일을 닫는 방법 (0) | 2023.03.24 |
키보드가 나타나면 이동 위젯의 크기가 조정됩니다. 어떻게 이것을 예방할 수 있을까요? (0) | 2023.03.23 |