انقسام من قبل الفاصلة والمساحة البيضاء في بيثون

StackOverflow https://stackoverflow.com/questions/4071396

  •  28-09-2019
  •  | 
  •  

سؤال

لدي بعض رمز بيثون الذي ينقسم على الفاصلة ، ولكن لا يجرد المسافة البيضاء:

>>> string = "blah, lots  ,  of ,  spaces, here "
>>> mylist = string.split(',')
>>> print mylist
['blah', ' lots  ', '  of ', '  spaces', ' here ']

أفضل أن ينتهي بإزالة المسافة البيضاء مثل هذا:

['blah', 'lots', 'of', 'spaces', 'here']

أدرك أنه يمكنني الحصول على حلقة من خلال القائمة وقطعة () كل عنصر ، لكن بما أن هذا بيثون ، أعتقد أن هناك طريقة أسرع وأسهل وأكثر أناقة للقيام بذلك.

هل كانت مفيدة؟

المحلول

استخدم فهم القائمة - أبسط ، وسهلة القراءة مثل أ for عقدة.

my_string = "blah, lots  ,  of ,  spaces, here "
result = [x.strip() for x in my_string.split(',')]
# result is ["blah", "lots", "of", "spaces", "here"]

نرى: مستندات بيثون على فهم القائمة
شرح جيد 2 الثاني لفهم القائمة.

نصائح أخرى

تقسيم باستخدام تعبير منتظم. لاحظ أنني جعلت القضية أكثر عمومية مع المساحات الرائدة. فهم القائمة هو إزالة السلاسل الفارغة في الأمام والخلف.

>>> import re
>>> string = "  blah, lots  ,  of ,  spaces, here "
>>> pattern = re.compile("^\s+|\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['blah', 'lots', 'of', 'spaces', 'here']

هذا يعمل حتى لو ^\s+ لا يتطابق:

>>> string = "foo,   bar  "
>>> print([x for x in pattern.split(string) if x])
['foo', 'bar']
>>>

إليك لماذا تحتاج إلى ^ S+:

>>> pattern = re.compile("\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['  blah', 'lots', 'of', 'spaces', 'here']

رؤية المساحات الرائدة في بلاه؟

التوضيح: أعلاه يستخدم مترجم Python 3 ، ولكن النتائج هي نفسها في Python 2.

جئت لأضيف:

map(str.strip, string.split(','))

ولكن رأى أنه قد ذكره بالفعل من قبل جيسون أورندرف في تعليق.

قراءة تعليق Glenn Maynard في نفس الإجابة التي تشير إلى القائمة على شمولية على الخريطة ، بدأت أتساءل عن السبب. لقد افترضت أنه يعني لأسباب الأداء ، ولكن بالطبع ربما كان يعني لأسباب أسلوبية ، أو أي شيء آخر (جلين؟).

لذلك تم الكشف عن اختبار سريع (ربما معيبة؟) على الصندوق الذي يطبق الأساليب الثلاثة في حلقة:

[word.strip() for word in string.split(',')]
$ time ./list_comprehension.py 
real    0m22.876s

map(lambda s: s.strip(), string.split(','))
$ time ./map_with_lambda.py 
real    0m25.736s

map(str.strip, string.split(','))
$ time ./map_with_str.strip.py 
real    0m19.428s

صناعة map(str.strip, string.split(',')) الفائز ، على الرغم من أنه يبدو أنهم جميعًا في نفس الملعب.

من المؤكد أنه على الرغم من أنه لا ينبغي بالضرورة استبعاد الخريطة (مع أو بدون Lambda) لأسباب الأداء ، وبالنسبة لي يكون ذلك واضحًا على الأقل مثل فهم القائمة.

يحرر:

Python 2.6.5 على Ubuntu 10.04

فقط قم بإزالة المساحة البيضاء من السلسلة قبل تقسيمها.

mylist = my_string.replace(' ','').split(',')

أعلم أن هذا قد تم الرد عليه بالفعل ، ولكن إذا انتهت من القيام بذلك كثيرًا ، فقد تكون التعبيرات العادية طريقة أفضل للذهاب:

>>> import re
>>> re.sub(r'\s', '', string).split(',')
['blah', 'lots', 'of', 'spaces', 'here']

ال \s يطابق أي حرف من المسافة البيضاء ، ونستبدلها بسلسلة فارغة ''. يمكنك العثور على مزيد من المعلومات هنا: http://docs.python.org/library/re.html#re.sub

s = 'bla, buu, jii'

sp = []
sp = s.split(',')
for st in sp:
    print st
import re
result=[x for x in re.split(',| ',your_string) if x!='']

هذا يفي بالغرض بالنسبة لي.

re (كما في التعبيرات العادية) يسمح بالقسمة على أحرف متعددة في وقت واحد:

$ string = "blah, lots  ,  of ,  spaces, here "
$ re.split(', ',string)
['blah', 'lots  ', ' of ', ' spaces', 'here ']

هذا لا يعمل بشكل جيد لسلسلة مثالك ، ولكنه يعمل بشكل جيد للحصول على قائمة مفصول بين الفواصل. لسلسلة المثال الخاصة بك ، يمكنك الجمع بين قوة إعادة التقسيم أنماط regex للحصول على تأثير "انقسام على هذا أو هذا".

$ re.split('[, ]',string)
['blah',
 '',
 'lots',
 '',
 '',
 '',
 '',
 'of',
 '',
 '',
 '',
 'spaces',
 '',
 'here',
 '']

لسوء الحظ ، هذا قبيح ، لكن أ filter سيفعل الحيلة:

$ filter(None, re.split('[, ]',string))
['blah', 'lots', 'of', 'spaces', 'here']

هاهو!

map(lambda s: s.strip(), mylist) سيكون أفضل قليلاً من الحلقات الصريحة. أو لكل شيء في وقت واحد: map(lambda s:s.strip(), string.split(','))

import re
mylist = [x for x in re.compile('\s*[,|\s+]\s*').split(string)

ببساطة ، فاصلة أو مساحات بيضاء واحدة على الأقل مع/بدون مساحات بيضاء تسبق/التالية.

أرجوك حاول!

map(lambda s: s.strip(), mylist) سيكون أفضل قليلاً من الحلقات الصريحة.
أو لكل شيء في وقت واحد:

map(lambda s:s.strip(), string.split(','))

هذا في الأساس كل ما تحتاجه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top