2017-06-21 33 views
1

我想使用map,reduce,filter以更pythonic的方式編寫此代碼。有人可以幫助我。使用Python對字符串進行迭代3

這是一段簡單的代碼,它根據字符串中的位置將總值賦給字符串。 例如,對於該字符串abaacab

a b a a c a b 
1 2 3 4 occurrence of a 
    1   2 occurrence of b 
     1  occurrence of c 
1+1+2+3+1+4+2 = 14 

import sys 
check, total = {}, 0 
for i, v in enumerate(sys.argv[1]): 
    if v in check: 
     check[v] += 1 
    else: 
     check[v] = 1 
    total += check[v] 
print(total) 
+1

爲什麼downvote? –

+1

我還沒有投票,但我會想象,人們會期望一些研究努力或編程嘗試從你身邊。現在你基本上要求人們爲你寫一些代碼。 – quinz

+0

它是做什麼的? –

回答

1
import sys 
val = {v : sys.argv[1].count(v) for v in set(sys.argv[1])} 
total = sum(val[k] * (val[k] + 1) // 2 for k in val) 

3線... 1個進口和2行香草蟒。

第一行創建一個字符到計數的映射。然後,第二行查找列表理解中的每個字符的序列總和,第二個sum總和每個字符的總和。

輸出:

val: {'a': 4, 'c': 1, 'b': 2} 
total: 14 

警告:這是效率不高,因爲它計算計數的每個字符(線性複雜性)。

4

如果您想按照您當前的方式計算結果,我認爲您當前的代碼與Pythonic相似(唯一的例外是不必要的enumerate調用)。

但是,我認爲找到您的total的方法要比在計算時添加計數更好。由每個值貢獻的總部分可以直接從該值的最終計數中計算出來(這是一個三角形數字)。這意味着您可以一次計算出數值,並在最後計算總數。

以下是我會做:

import sys 
import collections 

counts = collections.Counter(sys.argv[1]) 
total = sum(n * (n+1) // 2 for n in counts.values()) 
print(total) 
+0

對於'n *(n + 1)// 2'來說,一個較慢但易於理解的替代方法是'sum(range(n + 1))'。 –

+0

又名我的回答。 :p –

+0

@Rawing這真的很慢,沒有優化? (我目前無法自己運行。) – bbastu

0

我會說你的代碼可以作出的唯一方法更Python是使用Counter對象,而不是一個普通dict,它簡化了實際的計數是由dict進行:

>>> from collections import Counter 
>>> counts = Counter() 
>>> s = "abaacab" 
>>> total = 0 
>>> for c in s: 
...  counts[c] += 1 
...  total += counts[c] 
... 
>>> total 
14 
1

所以願意,這裏是另一個答案是實際上你想要做什麼,你想要它。 Python3兼容,沒有在Python2上測試過。

from functools import reduce, partial 
total = reduce(lambda x, y: x + y, map(lambda x: x * (x + 1) // 2, map(partial(str.count, sys.argv[1]), set(sys.argv[1])))) 
print(total) 

輸出

14 

其分解:

partial(str.count, sys.argv[1]) ---- (1)限定其中map將適用於sys.argv高階函數。這樣,你的計數就被創建了。最終答案不需要字典,因此不會創建。

map(---(1)---, set(sys.argv[1])) ---- (2)適用的部分功能(1)

map(lambda x: x * (x + 1) // 2, ----(2)----) ----(3)採用由(2)中產生的計數,然後應用AP獲得的總和。

reduce(lambda x, y: x + y, ----(3)----)將其與(3)的總和相加。