You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询:同一联系人关联电话与邮箱合并的算法实现方案

解决思路与实现代码

这个问题的核心是识别通过电话/邮箱关联的连通记录组——只要两条记录共享电话或邮箱(哪怕是间接共享),就属于同一组,需要合并。这类问题用图论中的「连通分量」算法最适合,具体步骤如下:

步骤说明

  1. 按姓名分组:不同姓名的记录肯定属于不同联系人,先拆分处理。
  2. 构建关联图:对每个姓名组,把所有电话、邮箱都作为图的节点,每条原始记录对应一条「电话-邮箱」的边(表示两者关联)。
  3. 提取连通分量:找出图中所有互相连通的节点集合,每个集合就是一个需要合并的记录组。
  4. 映射并合并:把每条原始记录匹配到对应的连通分量,再按姓名+连通分量分组,拼接去重后的电话和邮箱。

具体代码实现

library(tidyverse)
library(igraph)

# 原始数据
contact <- tribble(
  ~name, ~phone, ~email,
  'John', 123, 'john_abc@gmail.com',
  'John', 456, 'john_abc@gmail.com',
  'John', 456, 'john_xyz@gmail.com',
  'John', 789, 'john_pqr@gmail.com'
)

contact_combined <- contact %>%
  # 按姓名分组处理
  group_by(name) %>%
  group_modify(function(data, .) {
    # 1. 构建边列表:每条记录的电话和邮箱作为一条边
    edges <- data %>%
      mutate(phone = as.character(phone)) %>%
      select(phone, email) %>%
      rename(from = phone, to = email)
    
    # 2. 创建图并提取连通分量
    graph <- graph_from_data_frame(edges, directed = FALSE)
    components <- components(graph)$membership
    
    # 3. 把每个节点(电话/邮箱)映射到对应的分量ID
    node_component <- enframe(components, name = "node", value = "component_id")
    
    # 4. 给每条原始记录匹配分量ID:通过电话或邮箱匹配
    data_with_component <- data %>%
      mutate(phone = as.character(phone)) %>%
      left_join(node_component, by = c("phone" = "node")) %>%
      left_join(node_component, by = c("email" = "node"), suffix = c("", "_email")) %>%
      # 取电话或邮箱对应的分量ID(两者必然属于同一分量)
      mutate(component_id = coalesce(component_id, component_id_email)) %>%
      select(-component_id_email)
    
    # 5. 按分量ID分组,拼接去重后的电话和邮箱
    data_with_component %>%
      group_by(component_id) %>%
      summarise(
        phone = str_c(unique(phone), collapse = ";"),
        email = str_c(unique(email), collapse = ";"),
        .groups = "drop"
      )
  }) %>%
  ungroup() %>%
  select(name, phone, email)

# 查看结果
contact_combined

运行后会得到期望的输出:

# A tibble: 2 × 3
  name  phone     email                                  
  <chr> <chr>     <chr>                                  
1 John  123;456   john_abc@gmail.com;john_xyz@gmail.com
2 John  789       john_pqr@gmail.com

关键逻辑解释

  • 图的构建:把电话和邮箱视为节点,每条记录的关联关系就是边,这样所有间接关联的节点(比如123→abc邮箱→456→xyz邮箱)会被归为同一个连通分量。
  • 连通分量匹配:每条记录通过电话或邮箱找到所属的分量ID,确保所有关联记录都被分到同一组。
  • 去重拼接:分组后对电话和邮箱去重再拼接,避免重复值。

内容的提问来源于stack exchange,提问作者msunij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:39:53