【问题标题】:Properly mapping first names to emails?正确地将名字映射到电子邮件?
【发布时间】:2014-04-24 00:48:27
【问题描述】:

我正在做一个研究项目,我有一个大约 200 个姓名和 6 个电子邮件地址的列表。要求是将这些电子邮件中的每封都映射到遵循此要求的单个电子邮件地址:

“以 A、B、C、D、E 开头的名称将映射到 email1。F、G、H、I、J 将映射到 email2”等等。

现在我正在尝试以“如果 nameA-E 开头然后 email1 的方式将这些名称映射到特定电子邮件的方法” ,而不是遍历所有名称并检查每个名称的首字母。有没有办法做到这一点?我认为 RegEx 可能会有所帮助,但不确定具体如何(可能类似于^[a-eA-E]?)

【问题讨论】:

  • 预期输出?预期输入?
  • 我已经解决了这个问题。我将遍历所有名称,执行if re.match('^[a-eA-E]', name) 并基于此分配电子邮件。如果我不清楚的话,预期的输出将是一个带有“name”和“email”键及其各自值的字典,而预期的输入是一个名称列表。

标签: python regex iterator


【解决方案1】:

re 模块有一个未记录的Scanner class,可用于将任意函数调用附加到正则表达式模式。当调用Scanner.scan 方法时,提供的文本将与每个正则表达式模式匹配,并在找到匹配项时调用关联的函数。当剩余文本与任何模式都不匹配时,扫描方法结束。

import re

def make_email(i):
    def email(scanner, token):
        print('{t}: Send to email{i}'.format(t=token, i=i))
    return email

scanner = re.Scanner(
    [(pat, make_email(i))                                    # 2
     for i, pat in enumerate((r"^[a-e]\w+", r"^[f-j]\w+"))]  # 1
    + [(r"\s+", None)],
    flags=re.IGNORECASE|re.MULTILINE)

scanner.scan("""\
Albert
Barry
Carrie
David
Erin
Franklin
Geoff
Harold
Isadore
Jay""")

打印

Albert: Send to email0
Barry: Send to email0
Carrie: Send to email0
David: Send to email0
Erin: Send to email0
Franklin: Send to email1
Geoff: Send to email1
Harold: Send to email1
Isadore: Send to email1
Jay: Send to email1

  1. 您可以在此处添加更多正则表达式模式。
  2. 使用 2 元组列表初始化 Scanner 类。每个 2 元组由一个正则表达式模式和相关的回调组成 功能。

【讨论】:

  • 正是我要找的。不敢相信它是无证的 - 看起来为此目的是为了做出贡献!非常感谢。
  • -1 我只是认为这是解决实际问题的一种非常笨拙的方法。这是有趣的信息,但这里不需要正则表达式。
【解决方案2】:

简单直接的解决方案是创建一个以正则表达式为键的简单字典,然后循环遍历它们。

import re
mappings = { r'^[a-e]': "email0", r'^[f-j]': "email1" }
for name in names:
    for regex in mappings:
        if re.match(regex, name, flags=re.IGNORECASE):
            print "%s: send to %s" % (name, mappings[regex])
            break
    else:
        print "%s: no match" % name

如果您在工业规模上执行此操作,您可能希望使用 re.compile() 预编译正则表达式,但为了获得快速而肮脏的解决方案,这可以完成工作。

【讨论】:

  • -1 我不想投反对票,也不想发表评论——我已经在线程的其他地方提出了反对正则表达式的理由。
  • 我写这篇文章主要是为了指出一个比公认答案不那么深奥的解决方案。对于这个简单的案例,同意正则表达式可能是多余的,但这应该很容易扩展到映射不是那么简单的各种其他类似用例。
【解决方案3】:

您只需要知道每个名称中的第一个字母,并将其映射到电子邮件地址。你不需要正则表达式。

def address(name):

    addresses = ['foo@bar.com', 'spam@eggs.org', ... ]

    i = 'abcdefghijklmnopqrstuvwxyz'.find(name[0].lower()) // 5
    return addresses[i]

然后您想要遍历名称。

for name in names: print(name, address(name))

【讨论】:

  • 这假设电子邮件地址真的那么简单。我猜实际上他们不是。您可以将它们放在一个数组中并使用 n(name) 作为该数组的索引,但此时字典会更有意义。
  • 问题非常清楚,以特定字母开头的名称和电子邮件地址之间的映射,因此您仍然不想为此使用re。承认,如果电子邮件地址更复杂,您可能会使用字典。我只是想表明接受的答案是多余的。
  • 我更新了答案以显示如何按照您的建议使用列表。所定义的问题不需要比这更复杂的任何东西。
猜你喜欢
  • 1970-01-01
  • 2011-10-14
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-24
  • 2020-10-05
相关资源
最近更新 更多