Python: استخراج الأرقام من سلسلة



regex string (8)

أود استخراج جميع الأرقام الموجودة في سلسلة. ما هو الأنسب للغرض أو التعبيرات العادية أو طريقة isdigit() ؟

مثال:

line = "hello 12 hi 89"

نتيجة:

[12, 89]

https://code.i-harness.com


jmnas ، أعجبتني إجابتك ، لكنها لم تجد العوامات. أنا أعمل على برنامج نصي لتحليل رمز الذهاب إلى مطحنة التصنيع باستخدام الحاسب الآلي وتحتاج إلى العثور على كل من الأبعاد X و Y التي يمكن أن تكون أعدادًا صحيحة أو عائمة ، لذلك أعدلت شفرتك إلى ما يلي. هذا يجد int ، تطفو مع vals الإيجابية والسلبية. لا تزال لا تجد القيم المنسقة ست عشري ولكن يمكنك إضافة "س" و "أ" من خلال "F" إلى tuple num_char وأعتقد أنها ستحلل أشياء مثل "0x23AC".

s = 'hello X42 I\'m a Y-32.35 string Z30'
xy = ("X", "Y")
num_char = (".", "+", "-")

l = []

tokens = s.split()
for token in tokens:

    if token.startswith(xy):
        num = ""
        for char in token:
            # print(char)
            if char.isdigit() or (char in num_char):
                num = num + char

        try:
            l.append(float(num))
        except ValueError:
            pass

print(l)

أستخدم كلمة regexp:

>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']

هذا من شأنه أيضا أن يطابق 42 من bla42bla . إذا كنت تريد فقط تحديد الأرقام بواسطة حدود الكلمات (المسافة ، النقطة ، الفاصلة) ، فيمكنك استخدام \ b:

>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']

لتنتهي بقائمة الأرقام بدلاً من قائمة السلاسل:

>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]

أفضل خيار وجدته هو أدناه. وسوف استخراج عدد ويمكن القضاء على أي نوع من شار.

def extract_nbr(input_str):
    if input_str is None or input_str == '':
        return 0

    out_number = ''
    for ele in input_str:
        if ele.isdigit():
            out_number += ele
    return float(out_number)    

أنا مندهش لرؤية أي أحد ذكر حتى الآن استخدام itertools.groupby كبديل لتحقيق ذلك.

يمكنك استخدام itertools.groupby مع str.isdigit() لاستخراج الأرقام من السلسلة على النحو التالي:

from itertools import groupby
my_str = "hello 12 hi 89"

l = [int(''.join(i)) for is_digit, i in groupby(my_str, str.isdigit) if is_digit]

القيمة الممسوكة بواسطة l ستكون:

[12, 89]

ملاحظة: هذا فقط لغرض التوضيح لإظهار أنه كبديل يمكننا أيضا استخدام groupby لتحقيق ذلك. لكن هذا ليس حلا موصى به. إذا كنت ترغب في تحقيق ذلك ، فيجب أن تستخدم الإجابة المقبولة على fmark استنادًا إلى استخدام فهم القائمة باستخدام str.isdigit كفلتر.


إذا كنت تعلم أنه سيكون هناك رقم واحد فقط في السلسلة ، أي "hello 12 hi" ، فيمكنك تجربة الفلتر.

فمثلا:

In [1]: int(filter(str.isdigit, '200 grams'))
Out[1]: 200
In [2]: int(filter(str.isdigit, 'Counters: 55'))
Out[2]: 55
In [3]: int(filter(str.isdigit, 'more than 23 times'))
Out[3]: 23

ولكن كن متأن !!! :

In [4]: int(filter(str.isdigit, '200 grams 5'))
Out[4]: 2005

تحتوي هذه الإجابة أيضًا على الحالة عندما يكون الرقم عائمًا في السلسلة

def get_first_nbr_from_str(input_str):
    '''
    :param input_str: strings that contains digit and words
    :return: the number extracted from the input_str
    demo:
    'ab324.23.123xyz': 324.23
    '.5abc44': 0.5
    '''
    if not input_str and not isinstance(input_str, str):
        return 0
    out_number = ''
    for ele in input_str:
        if (ele == '.' and '.' not in out_number) or ele.isdigit():
            out_number += ele
        elif out_number:
            break
    return float(out_number)

هذا أكثر من متأخر قليلاً ، ولكن يمكنك توسيع تعبير التعبير المعتاد لمراعاة الترميز العلمي أيضًا.

import re

# Format is [(<string>, <expected output>), ...]
ss = [("apple-12.34 ba33na fanc-14.23e-2yapple+45e5+67.56E+3",
       ['-12.34', '33', '-14.23e-2', '+45e5', '+67.56E+3']),
      ('hello X42 I\'m a Y-32.35 string Z30',
       ['42', '-32.35', '30']),
      ('he33llo 42 I\'m a 32 string -30', 
       ['33', '42', '32', '-30']),
      ('h3110 23 cat 444.4 rabbit 11 2 dog', 
       ['3110', '23', '444.4', '11', '2']),
      ('hello 12 hi 89', 
       ['12', '89']),
      ('4', 
       ['4']),
      ('I like 74,600 commas not,500', 
       ['74,600', '500']),
      ('I like bad math 1+2=.001', 
       ['1', '+2', '.001'])]

for s, r in ss:
    rr = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", s)
    if rr == r:
        print('GOOD')
    else:
        print('WRONG', rr, 'should be', r)

يعطي كل خير!

بالإضافة إلى ذلك ، يمكنك إلقاء نظرة على التضمين التوضيحي المدمج في AWS Glue


# extract numbers from garbage string:
s = '12//n,[email protected]#$%3.14kjlw0xdadfackvj1.6e-19&*ghn334'
newstr = ''.join((ch if ch in '0123456789.-e' else ' ') for ch in s)
listOfNumbers = [float(i) for i in newstr.split()]
print(listOfNumbers)
[12.0, 3.14, 0.0, 1.6e-19, 334.0]




numbers