简体   繁体   English

使用Python 3迭代字符串

[英]Iterating a string using Python 3

I want to write this code in a more pythonic way using map, reduce, filter. 我想使用map,reduce,filter以更pythonic的方式编写此代码。 Can someone help me with that. 有人可以帮我吗。

This is a simple piece of code which assigns a total value to a string based on it's position in the string. 这是一段简单的代码,它根据字符串在字符串中的位置将总值分配给字符串。 For example, for the string abaacab 例如,对于字符串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)

If you want to calculate the result in the way you're currently doing it, I think your current code is about as Pythonic as it can be (the only exception is the unnecessary enumerate call). 如果您想以当前执行的方式来计算结果,我认为您当前的代码与Pythonic差不多(唯一的例外是不必要的enumerate调用)。

However, I think there's a better way to find your total than adding up the counts as you make them. 但是,我认为找到total总比将计数加起来时有更好的方法。 The part of the total contributed by each value can be calculated directly from the final count of that value (it's a triangular number). 每个值贡献的总额的一部分可以直接从该值的最终计数(这是一个三角数)中计算得出。 This means you can count the values in one go and figure out the total at the end. 这意味着您可以一口气计算值,最后算出总数。

Here's how I'd do it: 这是我的处理方式:

import sys
import collections

counts = collections.Counter(sys.argv[1])
total = sum(n * (n+1) // 2 for n in counts.values())
print(total)
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 lines... 1 import and 2 lines of vanilla python. 3行... 1导入和2行香草python。

The first line creates a mapping of chars to counts. 第一行创建字符到计数的映射。 Then, the second line finds the sum of sequence for each character inside a list comprehension, with a second sum to total the sums of each character. 然后,第二行找到列表推导中每个字符的序列总和,以及第二个sum以求和每个字符的总和。

Output: 输出:

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

Caveat: This is not efficient, since it calculates counts for each character (linear complexity). 警告:这是无效的,因为它会计算每个字符的计数(线性复杂度)。

SO willing, here's another answer that actually does what you want as you want it. 非常愿意,这是另一个答案, 实际上可以根据您的需要进行操作。 Python3 compliant, haven't tested on Python2. 兼容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)

Output 输出量

14

Breaking it down: 分解:

partial(str.count, sys.argv[1]) ---- (1) defines a higher order function which the map will apply to sys.argv . partial(str.count, sys.argv[1]) ---- (1)定义了map将应用于sys.argv高阶函数。 This way, your counts are created. 这样,您的计数就创建了。 A dict is not needed for the final answer so it is not created. 最终答案不需要字典,因此不会创建。

map(---(1)---, set(sys.argv[1])) ---- (2) applies the partial function (1) map(---(1)---, set(sys.argv[1])) ---- (2)应用偏函数(1)

map(lambda x: x * (x + 1) // 2, ----(2)----) ----(3) takes the counts generated by (2) and then applies AP to get the sum. map(lambda x: x * (x + 1) // 2, ----(2)----) ----(3)接受(2)生成的计数,然后应用AP获得和。

reduce(lambda x, y: x + y, ----(3)----) tops it off with a summation of the sums from (3). reduce(lambda x, y: x + y, ----(3)----)的总和求和。

The only way I would say your code could be made more Pythonic is by using a Counter object instead of a regular dict , which streamlines the actual counting being performed by the dict : 我要说的可以使您的代码更像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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM