2017-06-21 62 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)的总和相加。