计算后续信件

时间:2018-03-30 19:20:57

标签: python string frequency letter frequency-distribution

所以我正在尝试使用python实现将计算句子中下一个字母的代码。 所以,例如,

"""So I am trying to implement code that will count the next letter in a sentence, using 
python"""

最常见的字母一个接一个

  1. 代表's'

    • 'o':1
    • 'e':1
  2. 代表'o'

    • '':1
    • 'd':1
    • '你':1
    • 'n':1
  3. 我认为你明白了这个想法

    我已经编写了用于计算字母的代码

    def count_letters(word, char):
        count = 0
        for c in word:
            if char == c:
                count += 1
        return count
    

    正如你所看到的,这只是字母,而不是下一个字母。有人能帮我一把吗?

4 个答案:

答案 0 :(得分:3)

from collections import Counter, defaultdict

counts = defaultdict(Counter)

s = """So I am trying to implement code that will count the next letter in a sentence, using
python""".lower()

for c1, c2 in zip(s, s[1:]):
    counts[c1][c2] += 1

(除了更简单之外,这应该明显快于pault的答案,因为没有为每个字母迭代字符串)

google中未在代码中命名的概念:

  • for c1, c2 in ...(即有两个变量的事实):元组解包
  • s[1:]:切片。基本上这是第一个字符后面的字符串的副本。

答案 1 :(得分:1)

这是使用collections.Counter的方式:

假设您提供的字符串存储在变量s中。

首先,我们迭代s中所有小写字母的集合。我们通过创建另一个字符串s_lower来执行此操作,该字符串将字符串s转换为小写。然后我们用set构造函数包装它以获得唯一值。

对于每个char,我们遍历字符串并检查前一个字母是否等于char。如果是这样,我们将其存储在列表中。最后,我们将此列表传递给collections.Counter构造函数,该构造函数将计算出现次数。

每个计数器都存储在字典counts中,其中键是字符串中的唯一字符。

from collections import Counter

counts = {}
s_lower = s.lower()
for char in set(s_lower):
    counts[char] = Counter(
        [c for i, c in enumerate(s_lower) if i > 0 and s_lower[i-1] == char]
    )

对于您的字符串,它具有以下输出:

>>> print(counts['s'])
#Counter({'i': 1, 'e': 1, 'o': 1})

>>> print(counts['o'])
#Counter({' ': 2, 'd': 1, 'n': 1, 'u': 1})

需要注意的是,此方法将遍历每个唯一字符的整个字符串,这可能会使大型列表变慢。

以下是使用collections.Countercollections.defaultdict的替代方法,它只循环遍历字符串一次:

from collections import defaultdict, Counter

def count_letters(s):
    s_lower = s.lower()
    counts = defaultdict(Counter)
    for i in range(len(s_lower) - 1):
        curr_char = s_lower[i]
        next_char = s_lower[i+1]
        counts[curr_char].update(next_char)
    return counts

counts = count_letters(s)

我们遍历字符串中的每个字符(除了最后一个),并且在每次迭代时我们使用下一个字符更新计数器。

答案 2 :(得分:1)

这是一种相对简洁的方法:

from itertools import groupby
from collections import Counter

def countTransitionFrequencies(text):
  prevNext = list(zip(text[:-1], text[1:]))
  prevNext.sort(key = lambda pn: pn[0])
  transitions = groupby(prevNext, lambda pn: pn[0])
  freqs = map(
    lambda kts: (kts[0], Counter(map(lambda kv: kv[1], kts[1]))), 
    transitions
  )
  return freqs

说明:

  1. zip创建包含(previous, next)个字符
  2. 的对列表
  3. 这些对按previous字符
  4. 排序和分组
  5. 然后使用next计算kv[1]个字符的频率(从Counter对中提取)。
  6. 排序并不是必需的,但不幸的是,这就是所提供的groupby的工作方式。

    一个例子:

    for k, v in countTransitionFrequencies("hello world"):
      print("%r -> %r" % (k, v))
    

    打印:

    ' ' -> Counter({'w': 1})
    'e' -> Counter({'l': 1})
    'h' -> Counter({'e': 1})
    'l' -> Counter({'l': 1, 'o': 1, 'd': 1})
    'o' -> Counter({' ': 1, 'r': 1})
    'r' -> Counter({'l': 1})
    'w' -> Counter({'o': 1})
    

答案 3 :(得分:0)

这应该可行,唯一的一点是它不对值进行排序,但可以通过创建一个包含元组列表(char,occurrence)的新字典并在元组[1]上使用有序函数来解决。

def countNext(word):
    d = {}
    word = word.lower()
    for i in range(len(word) - 1):
        c = word[i]
        cc = word[i+1]
        if(not c.isalpha() or not cc.isalpha()):
            continue
        if c in d:
            if cc in d[c]:
                d[c][cc] += 1
            else:
                d[c][cc] = 1
        else:
            d[c] = {}
            d[c][cc] = 1
    return d