development

패턴이나 모든 n 요소를 포함하지 않을 때 Python에서 문자열을 어떻게 안정적으로 분할합니까?

big-blog 2020. 10. 20. 07:52
반응형

패턴이나 모든 n 요소를 포함하지 않을 때 Python에서 문자열을 어떻게 안정적으로 분할합니까?


Perl에서는 다음을 수행 할 수 있습니다.

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

그리고 문자열에 패턴이 포함되어 있는지 여부에 관계없이 작동합니다.

그러나 Python에서는 작동하지 않습니다.

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

이러한 경우 오류를 방지하는 표준 방법은 무엇입니까?


예에서와 같이 두 부분으로 만 분할하는 경우 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.


Python 3을 사용하고 있으므로 쉽습니다. PEP 3132는 튜플에 할당 할 때 구문의 환영받은 단순화를 도입했습니다 . 확장 된 반복 가능한 압축 풀기 입니다. 과거에는 튜플의 변수에 할당하는 경우 할당 왼쪽에있는 항목 수가 오른쪽에있는 항목 수와 정확히 같아야합니다.

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)

따라서 a, *b = s.split(":")Perl 에서 동등한 것은

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

주의 : 우리는 사용하지 말아야 $a$b함께 사용할 때 특별한 의미를 갖고 있기 때문에 일반적으로 펄 sort. 여기에서는 Python 예제와의 일관성을 위해 사용했습니다.

파이썬에는 추가 트릭이 있습니다. 왼쪽에있는 튜플의 모든 요소를 ​​풀 수 있습니다.

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

제공 :

a: one b: ['two', 'three'] c: four

Whereas in the Perl equivalent, the array (@b) is greedy, and the scalar $c is 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";

Gives:

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

You are always free to catch the exception.

For example:

some_string = "foo"

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

If assigning the whole original string to a and an empty string to b is the desired behaviour, I would probably use str.partition() as eugene y suggests. However, this solution gives you more control over exactly what happens when there is no separator in the string, which might be useful in some cases.


split will always return a list. a, b = ... will always expect list length to be two. You can use something like l = string.split(':'); a = l[0]; ....

Here is a one liner: a, b = (string.split(':') + [None]*2)[:2]


How about using Regular Expressions:

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

in 3.X:

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

in 2.X:

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

This way you can also use regular expressions to split(i. e. \d)

참고URL : https://stackoverflow.com/questions/38149470/how-do-i-reliably-split-a-string-in-python-when-it-may-not-contain-the-pattern

반응형