2017-09-13 15 views
1

私はPythonのreライブラリを使ってこれを試しました。 ファイルからは、複数の行に棒で区切られた要素( '|')が含まれています。私はそれらをリストに入れて、私が必要とするのはそれらを操作するために数字を内部に入れることです。Pythonの正規表現で文字列から十進数を抽出する

これは私が分割したい文字列のいずれかのようになります。

>>print(line_input) 
>>[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605] 

と私の意図は、角括弧の間の各要素をベクトルを形成することです。

私はこの正規表現

>>test_pattern="\|\[(\d*(\.\d+)?), (\d*(\.\d+)?), (\d*(\.\d+)?)]" 

を作成したが、結果は少し混乱しています。特に、結果は

>>vectors = re.findall(test_pattern, line_input) 

>>print(vectors) 
>>[('240', '', '7821', '', '0', '', '12', '', '605', '', '0', '', '3', ''), ('1.5', '.5', '7881.25', '.25', '0', '', '0', '', '0', '', '0', '', '0', ''), ('23437', '', '76611', '', '0', '', '0', '', '0', '', '605', '', '605', '')] 

小文字の部分が重複する理由は分かりません。私はほとんどそれを得ることを知っています、少なくとも、私はそれが小さな簡単な詳細だと確信していますが、私は取得しません。

ありがとうございます。

+0

空白は、おそらくあなたの桁正規表現から来ています。 '(\ d *(\。\ d +)?)'は空の文字列にマッチします。 ( '\ d *'は0桁以上の数字にマッチし、 '(\。\ d +)?' *オプションで*は '.'の後の1桁以上に一致します。 '' '') – 0x5453

+0

はい、@ 0x5453のように、これらの空白は空の可能な小数です。あなたの 'vectors'変数には空であるかどうかにかかわらず、すべての一致するグループが含まれます。だから、小数点があるときは、外部グループ '(\ d *(\。\ d +)?)'と内部グループ '(\。\ d +)?一致しないグループにします。 –

答えて

1

それらのブランクが空可能小数です。 vectors変数には、空であってもいなくても、すべてのキャプチャグループが含まれます。したがって、小数点がある場合は、外部グループ(\d*(\.\d+)?)と内部グループ(\.\d+)?の1つが一致します。非キャプチャグループ内で行います。

(\d+(?:\.\d+)?)

注:私はまた、小数点の前に番号を(もしあれば)を必要とし、それを変更しました。

0

あなたはこれを試すことができます。

import re 
s = "[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]" 
data = re.findall("\d+\.*\d+", s) 

出力:

['240', '7821', '12', '605', '1.5', '7881.25', '543', '876', '121', '237', '761', '61', '605', '605'] 
+1

'\ d + \。* \ d +'は少なくとも2桁の数字にのみ一致します。あなたはおそらく '\ d +(\。\ d +)? – 0x5453

0

これを行うには、別の方法(入力形式が異なる場合は堅牢でない可能性があります)は、文字列を '] | ['に分割してリストを取得し、 '、'で分割して値を取得します。

from decimal import Decimal 
input_str = '[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]' 

# ignore the first and last '[' and ']' chars, then split on list separators 
list_strs = input_str[1:-1].split(']|[') 

# Split on ', ' to get individual decimal values 
int_lists = [[Decimal(i) for i in s.split(', ')] for s in list_strs] 

# int_lists contains a list of lists of decimal values, like the input format 

for l in int_lists: 
    print(', '.join(str(d) for d in l)) 

結果

240, 7821, 0, 12, 605, 0, 3 
1.5, 7881.25, 0, 543, 876, 0, 121 
237, 761, 0, 61, 7, 605, 605 
0

正規表現は、その場所を持っています。しかし、pyparsingで書かれた文法は、しばしば書きやすく、読みやすくなります。

>>> import pyparsing as pp 

数値は、数字とピリオド/フルストップ文字で構成された単語に似ています。それらの後ろにカンマが続くこともあります。リストの

>>> number = pp.Word(pp.nums+'.') + pp.Optional(',').suppress() 

一つの任意続く、我々はまた、抑制右括弧、続いて、一つ以上の数字が続く我々が抑制左括弧、(ちょうど定義した通り)で構成されバー文字は、再び抑制されます。 (ちなみに、この括弧は、ある程度、括弧がリストを閉じるので冗長です。)

Groupを構文全体に適用することで、pyparsingは、私たちが抑制していない項目を別のPythonリストにまとめるようにします。

>>> one_list = pp.Group(pp.Suppress('[') + pp.OneOrMore(number) + pp.Suppress(']') + pp.Suppress(pp.Optional('|'))) 

リスト全体は1つ以上のリストに過ぎません。

>>> whole = pp.OneOrMore(one_list) 

はここで、我々は結果rに解析

>>> line_input = '[240, 7821, 0, 12, 605, 0, 3]|[1.5, 7881.25, 0, 543, 876, 0, 121]|[237, 761, 0, 61, 7, 605, 605]' 

を...入力です。

>>> r = whole.parseString(line_input) 

結果リストを表示できます。

>>> r[0] 
(['240', '7821', '0', '12', '605', '0', '3'], {}) 
>>> r[1] 
(['1.5', '7881.25', '0', '543', '876', '0', '121'], {}) 
>>> r[2] 
(['237', '761', '0', '61', '7', '605', '605'], {}) 

おそらく、数字を数字にしたいと思うでしょう。この場合、を知っています。リスト内の文字列は浮動小数点数または整数を表します。

>>> for l in r.asList(): 
...  [int(_) if _.isnumeric() else float(_) for _ in l] 
... 
[240, 7821, 0, 12, 605, 0, 3] 
[1.5, 7881.25, 0, 543, 876, 0, 121] 
[237, 761, 0, 61, 7, 605, 605] 
関連する問題