Python - 提取序列中所有驼峰命名单词

3
我会尽力帮助您翻译相关的IT技术内容,以下是需要翻译的内容:

我想返回一个以大写字母或标题格式开头的字符串中所有单词的列表,这些单词在序列中。

例如,在字符串John Walker Smith is currently in New York中,我想按如下列表返回:

['John Walker Smith', 'New York']

我的代码只在有两个标题单词时才起作用。如何扩展它以选择超过两个连续的标题单词。

def get_composite_names(s):
    l = [x for x in s.split()]
    nouns = []
    for i in range(0,len(l)):
        if i > len(l)-2:
            break
        if l[i] == l[i].title() and l[i+1] == l[i+1].title():
                temp = l[i]+' '+l[i+1]
                nouns.append(temp)
    return nouns

你尝试使用正则表达式了吗? - ma3oun
我不确定如何通过正则表达式解决单词顺序的问题。你能提供一个例子吗?我使用 string.title() 来获取首字母大写的单词。 - jax
看一下真实大小写:https://www.cs.cmu.edu/~llita/papers/lita.truecasing-acl2003.pdf - alvas
4个回答

7

以下是一种不使用正则表达式来实现此功能的方法:

from itertools import groupby

string = "John Walker Smith  is currently in New York"

groups = []

for key, group in groupby(string.split(), lambda x: x[0].isupper()):
    if key:
        groups.append(' '.join(list(group)))

print groups
# ['John Walker Smith', 'New York']

不将标题词作为列表中的一个元素进行分组。 - jax
@jax,没问题,很容易解决——请查看修订后的答案。 - cmaher

0
在 while 循环中,当我们遇到一个首字母大写的单词时,我们将其添加到列表 words 中。
当我们遇到一个非首字母大写的单词时,如果 words 不为空,就将首字母大写的单词添加进去,并重置 words 列表。
import re

s = 'abcd John Walker Smith is currently in New York'

def get_title_case_words(s):
  s = s.split()
  r = re.compile(r"[A-Z][a-z]*")

  def is_title_case(word):
    return r.match(word)

  i = 0
  res = []
  words = []
  while i < len(s):
    if is_title_case(s[i]):
      words.append(s[i])
    else:
      if words:
        res.append(' '.join(words))
        words = []

    i += 1

  if words:
    res.append(' '.join(words))

  return res

print(get_title_case_words(s))

1
我找到了一个解决方案,我认为它可以工作:re.findall('([A-Z][\w-]*(?:\s+[A-Z][\w-]*)+)', s)。它返回这些单词的列表。 - jax
不错!看起来似乎没有匹配到一个首字母大写的单词。它将无法在“John Walker Smith目前在New York”的语句中找到“New”。 - Eric

0

这似乎大致做到了你想要的,它保留了标点符号和单字母词。我不确定这是否是你想要的,但希望这段代码能为你提供一个良好的起点,如果还不够,请继续完善。

def get_composite_names(s):
    l = [x for x in s.split()]
    nouns = []
    current_title = None
    for i in range(0, len(l)):
        if l[i][0].isupper():
            if (current_title is not None):
                current_title = " ".join((current_title, l[i]))
            else:
                current_title = l[i]
        else:
            if (current_title is not None):
                nouns.append(current_title)
                current_title = None

    if (current_title is not None):
        nouns.append(current_title)
        current_title = None

    return nouns

print(get_composite_names("Hello World my name is John Doe"))

#returns ['Hello World', 'John Doe']

print(get_composite_names("I live in Halifax."))

#returns ['I', 'Halifax.']

print(get_composite_names("Even old New York was once New Amsterdam"))

#returns ['Even', 'New York', 'New Amsterdam']

0

它并不完美(而且我对正则表达式也不是很擅长),但我成功生成了这个似乎符合你要求的正则表达式:

(?:(?:[A-Z]{1}[a-z]*)(?:$|\s))+

给定字符串“John Walker Smith is currently in New York And he feels Great”,将匹配“John Walker Smith”、“New York”和“Great”。
有人可能会攻击我的正则表达式 - 随时编辑此答案以进行改进。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接