web-dev-qa-db-ja.com

パターンまたはn個の要素がすべて含まれていない可能性がある場合、Pythonで文字列を確実に分割するにはどうすればよいですか?

Perlでは、次のことができます。

my ($x, $y) = split /:/, $str;

また、文字列にパターンが含まれているかどうかにかかわらず機能します。

Pythonでは、しかしこれは機能しません:

a, b = "foo".split(":")  # ValueError: not enough values to unpack

そのような場合にエラーを防ぐための標準的な方法は何ですか?

74
planetp

(例のように)2つの部分だけに分割する場合は、 str.partition() を使用して、保証された引数アンパックサイズ3を取得できます。

_>>> a, sep, b = 'foo'.partition(':')
>>> a, sep, b
('foo', '', '')
_

str.partition()は、区切り文字が見つかったかどうかに関係なく、常に3タプルを返します。

Python 3.xの別の代替方法は、 拡張反復可能アンパック を使用することです。

_>>> a, *b = 'foo'.split(':')
>>> a, b
('foo', [])
_

これにより、最初の分割アイテムがaに割り当てられ、残りのアイテム(存在する場合)のリストがbに割り当てられます。

111
Eugene Yarmash

Python 3です。簡単です。PEP3132は、タプルに割り当てる際の構文の歓迎すべき簡素化を導入しました-拡張反復可能アンパック。タプルの変数に割り当てる場合、割り当ての左側の項目の数は右側の項目の数と正確に等しくなければなりません。

Python 3では、左側の変数にアスタリスク*を接頭辞としてリストとして指定できます。これにより、変数を右側に入力しながら、できるだけ多くの値を取得できます(これは、タプルの長さがわからないときに多くの厄介なスライスを回避します。

_a, *b = "foo".split(":")  
print("a:", a, "b:", b)
_

与える:

_a: foo b: []
_

次のコメントとディスカッションを編集します。

Perlバージョンと比較すると、これはかなり異なりますが、Python(3)の方法です。Perlバージョンと比較すると、re.split()はより類似しています。ただし、単一の文字で分割するためにREエンジンを呼び出すことは、不必要なオーバーヘッドです。

Pythonで複数の要素を使用する場合:

_s = 'hello:world:sailor'
a, *b = s.split(":")
print("a:", a, "b:", b)
_

与える:

_a: hello b: ['world', 'sailor']
_

ただし、Perlでは:

_my $s = 'hello:world:sailor';
my ($a, $b) = split /:/, $s;
print "a: $a b: $b\n";
_

与える:

_a: hello b: world
_

Perlでは、追加の要素が無視または失われていることがわかります。 Python必要に応じて複製するのはかなり簡単です:

_s = 'hello:world:sailor'
a, *b = s.split(":")
b = b[0]
print("a:", a, "b:", b)
_

したがって、Perlでa, *b = s.split(":")と同等なものは

_my ($a, @b) = split /:/, $s;
_

NB:sortと共に使用すると特別な意味を持つため、一般的なPerlでは_$a_と_$b_を使用しないでください。ここではPythonの例との一貫性のためにそれらを使用しました。

Pythonには余分なトリックがあります。左側のTupleの任意の要素に展開できます。

_s = "one:two:three:four"
a, *b, c = s.split(':')
print("a:", a, "b:", b, "c:", c)
_

与える:

_a: one b: ['two', 'three'] c: four
_

一方、Perlでは、配列(_@b_)は貪欲で、スカラー_$c_はundefです:

_use strict;
use warnings;

my $s = 'one:two:three:four';
my ($a, @b, $c) = split /:/, $s;
print "a: $a b: @b c: $c\n";
_

与える:

_Use of uninitialized value $c in concatenation (.) or string at gash.pl line 8.
a: one b: two three four c: 
_
60
cdarke

例外はいつでもキャッチできます。

例えば:

_some_string = "foo"

try:
    a, b = some_string.split(":")
except ValueError:
    a = some_string
    b = ""
_

元の文字列全体をaに割り当て、空の文字列をbに割り当てることが望ましい場合は、eugene yが示唆するように、おそらくstr.partition()を使用します。ただし、このソリューションを使用すると、文字列に区切り文字がない場合の動作をより正確に制御できるため、場合によっては便利です。

22

splitは常にリストを返します。 _a, b = ..._は常にリストの長さが2であることを期待します。 l = string.split(':'); a = l[0]; ...のようなものを使用できます。

ライナーは1つです:a, b = (string.split(':') + [None]*2)[:2]

17
Aaron Schif

正規表現の使用はどうですか:

import re 
string = 'one:two:three:four'

3.Xの場合:

a, *b = re.split(':', string)

2.Xの場合:

a, b = re.split(':', string)[0], re.split(':', string)[1:]

この方法では、正規表現を使用してsplit(i。e。\ d)することもできます

3
Cheyn Shmuel