2012-03-13 36 views
1

以下代碼Ruby代碼將迭代源字符串並生成由'。'分隔的累積字詞列表。字符,除了最後一個'。'之後的字符。Ruby代碼的慣用Python版本,帶有一個用於測試語句的while循環?

例如,給 'Company.Dept.Group.Team' 的源串,結果將是... [ 「Company.Dept.Group」, 「Company.Dept」, 「公司」]

鑑於Python中的while循環(我相信)只會測試一個表達式而不是如下所示的語句,那麼最好如何在慣用Python中編寫它?

#ruby 
source = 'Company.Dept.Group.Team' 
results = [] 

temp = source.clone 
while (i = temp.rindex('.')) # test statement not supported in Python? 
    temp = temp[0...i] 
    results << temp 
end 

p results # >> ["Company.Dept.Group", "Company.Dept", "Company"] 
+0

是的,據我所知,Python中不允許assigments中,如果條件......這可能是這種方便的事情的時候。 – moooeeeep 2012-03-13 22:12:00

回答

2

Python的成語是這樣的:

while True: 
    i = temp.rindex('.') 
    if not i: 
     break 
    ... 
+2

'rindex'引發了一個ValueError,但是,所以這不會像書面那樣工作。 – DSM 2012-03-13 21:41:36

+0

另外,'如果不是我'將無論如何都是錯誤的,因爲'0'是字符串中的有效位置。如果找不到字符串,則rfind()將返回「-1」。 – 2012-03-13 21:52:35

+0

我將此標記爲答案,因爲您首先使用'while True:'作爲測試語句的Ruby while循環的Python慣用等價物。我認爲我可能使用的確切代碼是rfind()而不是rindex(),然後測試-1以打破。非常感謝! – Aryeh 2012-03-13 23:18:36

0

我會做

>>> import re 
>>> source = 'Company.Dept.Group.Team' 
>>> results = [source[:m.start()] for m in re.finditer(r"\.", source)] 
>>> results 
['Company', 'Company.Dept', 'Company.Dept.Group'] 

(使用reversed(results)如果你想顛倒順序)。

你的代碼的Python的或多或少的直譯是

source = 'Company.Dept.Group.Team' 
results = [] 
temp = source 

while True: 
    try: 
     i = temp.rindex('.') 
     temp = temp[:i]  
     results.append(temp) 
    except ValueError: 
     break 
print(results) 
1
>>> source = 'Company.Dept.Group.Team' 
>>> last = [] 
>>> [last.append(s) or '.'.join(last) for s in source.split('.')[:-1]] 
['Company', 'Company.Dept', 'Company.Dept.Group'] 
+1

有副作用的列表理解?通常,這並不是激動人心的「慣用Python」。 – 2012-03-13 22:14:50

1

如果你習慣了Python中,你看到列表理解和迭代器/發電機無處不在!

Python的可能是

source = 'Company.Dept.Group.Team' 

# generate substrings 
temp = source.split(".") 
results = [".".join(temp[:i+1]) for i,s in enumerate(temp)] 

# pop the team (alternatively slice the team out above) 
results.pop() 

# reverse results 
result.reverse() 

print result # should yield ["Company.Dept.Group", "Company.Dept", "Company"] 

,但很可能有更地道的解決方案......

1

於一般做到這一點,我可能會做的事:

source = 'Company.Dept.Group.Team' 
split_source = source.split('.') 
results = ['.'.join(split_source[0:x]) for x in xrange(len(split_source) - 1, 0, -1)] 
print results 

一個文字翻譯會更像:

source = 'Company.Dept.Group.Team' 

temp = source 
results = [] 
while True: 
    i = temp.rfind('.') 
    if i < 0: 
     break 
    temp = temp[0:i] 
    results.append(temp) 

print results 

或者,如果你喜歡:

source = 'Company.Dept.Group.Team' 

temp = source 
results = [] 
try: 
    while True: 
     temp = temp[0:temp.rindex('.')] 
     results.append(temp) 
except ValueError: 
    pass 
print results 

或者:

source = 'Company.Dept.Group.Team' 

temp = source 
results = [] 
i = temp.rfind('.') 
while i > 0: 
    temp = temp[0:i] 
    results.append(temp) 
    i = temp.rfind('.') 

print results 

正如你指出,事實上,作爲一種表達,使這些情況有點不雅,你不能把分配。我認爲前一種情況 - 即「雖然是真的」 - 比最後一種更常見。

欲瞭解更多的背景,這個職位看起來還不錯:http://effbot.org/pyfaq/why-can-t-i-use-an-assignment-in-an-expression.htm

+0

非常感謝,尤其是那個出色的pyfaq鏈接。 – Aryeh 2012-03-13 23:20:17

+0

@Alex:「非常感謝」通常用upvotes表示:) – 2012-03-14 14:07:42