按域划分的唯一电子邮件地址


Unique email addresses by domain

我试图使以下函数每个域仅返回 1 封电子邮件。

示例:如果我输入函数:

email1@domain.com email2@domain.com email1@domain.com email1@domain.com email3@test.co.uk

我希望它返回

email1@domain.com email3@test.co.uk

这是当前函数:

function remove_duplicates($str) {
  # match all email addresses using a regular expression and store them
  # in an array called $results
  preg_match_all("(['w-]+(?:'.['w-]+)*@(?:['w-]+'.)+[a-zA-Z]{2,7})",$str,$results);
  # sort the results alphabetically
  sort($results[0]);
  # remove duplicate results by comparing it to the previous value
  $prev="";
  while(list($key,$val)=each($results[0])) {
    if($val==$prev) unset($results[0][$key]);
    else $prev=$val;
  }
  # process the array and return the remaining email addresses
  $str = "";
  foreach ($results[0] as $value) {
     $str .= "<br />".$value;
  }
  return $str;
};

任何想法如何实现这一目标?

大致如下:

$emails = array('email1@domain.com', 'email2@domain.com', 'email1@domain.com', 'email1@domain.com', 'email3@test.co.uk');
$grouped = array();
foreach ($emails as $email) {
    preg_match('/(?<=@)[^@]+$/', $email, $match);
    $grouped[$match[0]] = $email;
}
var_dump($grouped);

这会保留域的最后一个出现,如果需要,修改以保留第一个并不难。

您可以简单地使用 array_unique 函数为您完成工作:

$emails = explode(' ', $emailString);
$emails = array_unique($emails);

除非所有相等的主机名都在一个连续的序列中,否则prev的概念是不可靠的。如果您按主机名排序并提供排序功能,它会起作用,但这有点矫枉过正。

使用主机名构建一个数组,删除数组中已有主机名的条目。

我建议以下技巧/过程:

  1. 从一个字符串更改为地址数组。你用preg_match_all这样做,其他人可能会用explode这样做,一切似乎都是有效的。所以你已经有了这个。
  2. 从地址中提取域。你可以用正则表达式或其他东西再做一次,我会说这是微不足道的。
  3. 现在检查域是否已使用,如果没有,请选择该电子邮件地址。

最后一点可以通过使用数组和域作为键轻松完成。然后,您可以使用isset查看它是否已在使用中。

编辑:由于deceze选择了类似的答案(他覆盖了每个域的匹配项),因此以下代码示例略有变化。当您获得字符串输入时,我考虑逐步迭代它,以节省临时地址数组并立即进行地址和域解析。为此,您需要处理偏移量,这由 preg_match .实际上,preg_match_all类似的事情是可能的,但是,您将再次拥有该数组。

此代码将选择第一个并忽略每个域的其他地址:

$str = 'email1@domain.com email2@domain.com email1@domain.com email1@domain.com email3@test.co.uk';
$addresses = array();
$pattern = '/['w-]+(?:'.['w-]+)*@((?:['w-]+'.)+[a-zA-Z]{2,7})/';
$offset = 0;
while (preg_match($pattern, $str, $matches, PREG_OFFSET_CAPTURE, $offset)) {
    list(list($address, $pos), list($domain)) = $matches;
    isset($addresses[$domain]) || $addresses[$domain] = $address;
    $offset = $pos + strlen($address);
}