سؤال

وليون بايثون () والحشو وظائف مثل string.ljust () لا tabstop على علم، أي أنها علاج '\ ر' مثل أي حرف آخر وحيد العرض، وليس ليون الجولة تصل إلى أقرب مضاعف من tabstop . مثال:

len('Bear\tnecessities\t')

وهو 17 بدلا من 24 (أي 4+ (8-4) +11+ (8-3))

ويقول أريد أيضا pad_with_tabs(s) دالة على ان هذه

pad_with_tabs('Bear', 15) = 'Bear\t\t'

وتبحث عن تطبيقات بسيطة من هذه - الاكتناز وسهولة القراءة أولا، وكفاءة الثانية. هذا هو السؤال الأساسي ولكن غضب. gnibbler - يمكن أن تظهر لك حل Pythonic بحتة، حتى لو كان يقول 20x وأقل كفاءة

هل أنت متأكد أنك يمكن تحويل ذهابا وإيابا باستخدام str.expandtabs (TABWIDTH)، ولكن هذا في عالي الكعب. استيراد الرياضيات للحصول على TABWIDTH * int( math.ceil(len(s)*1.0/TABWIDTH) ) يبدو أيضا مثل مبالغة واسعة النطاق.

وأنا لا يمكن أن إدارة أي شيء أكثر أناقة من ما يلي:

TABWIDTH = 8

def pad_with_tabs(s,maxlen):
  s_len = len(s)
  while s_len < maxlen:
    s += '\t'
    s_len += TABWIDTH - (s_len % TABWIDTH)
  return s

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

s = pad_with_tabs(s, ...)

وعلى وجه الخصوص لم أستطع الحصول على النهج نظيفة باستخدام قائمة الفهم أو string.join (...)

''.join([s, '\t' * ntabs])

ودون خاص غلاف الحالات التي يكون فيها ليون (ق) هو <مضاعف صحيح من TABWIDTH، أو ليون (ق) => MAXLEN بالفعل.

ويمكن لأي شخص تظهر ليون أفضل () وpad_with_tabs () وظائف؟

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

المحلول

TABWIDTH=8
def my_len(s):
    return len(s.expandtabs(TABWIDTH))

def pad_with_tabs(s,maxlen):
    return s+"\t"*((maxlen-len(s)-1)/TABWIDTH+1)

لماذا يمكنني استخدام expandtabs() منتديات حسنا انها سريعة

$ python -m timeit '"Bear\tnecessities\t".expandtabs()'
1000000 loops, best of 3: 0.602 usec per loop
$ python -m timeit 'for c in "Bear\tnecessities\t":pass'
100000 loops, best of 3: 2.32 usec per loop
$ python -m timeit '[c for c in "Bear\tnecessities\t"]'
100000 loops, best of 3: 4.17 usec per loop
$ python -m timeit 'map(None,"Bear\tnecessities\t")'
100000 loops, best of 3: 2.25 usec per loop

وأي شيء بالتكرار عبر سلسلة الخاص بك سيكون أبطأ، لمجرد التكرار هو ~ 4 مرات أبطأ من expandtabs حتى عندما كنت لا تفعل شيئا في الحلقة.

$ python -m timeit '"Bear\tnecessities\t".split("\t")'
1000000 loops, best of 3: 0.868 usec per loop

وحتى تقسيم فقط على علامات التبويب وقتا أطول. كنت لا تزال بحاجة إلى كرر أكثر من الانقسام وسادة كل عنصر إلى tabstop

نصائح أخرى

وأعتقد gnibbler هو الأفضل بالنسبة لمعظم الحالات prectical. ولكن على أي حال، وهنا هو ساذج (دون محاسبة CR، LF الخ) حل لحساب طول سلسلة دون خلق توسيع نسخة:

def tab_aware_len(s, tabstop=8):
    pos = -1
    extra_length = 0
    while True:
        pos = s.find('\t', pos+1)
        if pos<0:
            return len(s) + extra_length
        extra_length += tabstop - (pos+extra_length) % tabstop - 1

وربما يمكن أن تكون مفيدة لبعض سلاسل ضخمة أو الذاكرة حتى الملفات المعينة. وهنا هي وظيفة الحشو الأمثل قليلا:

def pad_with_tabs(s, max_len, tabstop=8):
    length = tab_aware_len(s, tabstop)
    if length<max_len:
        s += '\t' * ((max_len-1)//tabstop + 1 - length//tabstop)
    return s

وTABWIDTH * int( math.ceil(len(s)*1.0/TABWIDTH) ) هو في الواقع ضخمة على القتل. يمكنك الحصول على نفس النتيجة أكثر من ذلك بكثير ببساطة. لi إيجابية وn، الاستخدام:

def round_up_positive_int(i, n):
    return ((i + n - 1) // n) * n

ويعمل هذا الإجراء فقط في أي لغة لقد استعملت من أي وقت مضى، بعد الترجمة المناسبة.

وبعد ذلك يمكنك القيام به next_pos = round_up_positive_int(len(s), TABWIDTH)

لزيادة طفيفة في الأناقة من التعليمات البرمجية الخاصة بك، بدلا من

while(s_len < maxlen):

استخدم هذا:

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