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

如何封装R函数,使其循环调用自身输出直至输入输出长度一致?

问题描述

我正在处理多字段的杂乱业主数据,示例数据如下:

library(tidyverse)
df <- structure(list(id = c("0049984000", "3502234000", "4029979100", 
                            "4331301000", "4690309000", "4690487000", "4690686000", "4702065000", 
                            "4980108200"), OWNER_NAME_1 = c("CLAUDEAN L RING REV TRUST", 
                                                            "S2 REAL ESTATE GROUP 5 LLC", "SAM STAIR", "S2 REAL ESTATE GROUP", 
                                                            "S2 REAL ESTATE GROUP 5 LLC", "S2 REAL ESTATE GROUP 5 LLC", "S2 REAL ESTATE GROUP 5 LLC", 
                                                            "S2 REAL ESTATE", "S2 REAL EST GROUP"),
                     OWNER_MAIL_ADDR = c("2045 PARADISE DR", 
                                         "11512 W WOODSIDE DR", "2925 W LINCOLN AVE", "2925 W LINCOLN AVE", 
                                         "2925 W LINCOLN AV", "2925 W LINCOLN AVE", "2925 W LINCOLN AV", 
                                         "11512 W WOODSIDE DR", "2925 W LINCOLN AVE"), 
                     OWNER_CITY_STATE = c("WEST BEND, WI", 
                                          "HALES CORNERS, WI", "MILWAUKEE, WI", "MILWAUKEE, WI", "MILWAUKEE, WI", 
                                          "MILWAUKEE, WI", "MILWAUKEE, WI", "HALES CORNERS, WI", "MILWAUKEE, WI"
                     )), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame"
                     ))

df
# A tibble: 9 × 4
  id         OWNER_NAME_1               OWNER_MAIL_ADDR     OWNER_CITY_STATE 
  <chr>      <chr>                      <chr>               <chr>            
1 0049984000 CLAUDEAN L RING REV TRUST  2045 PARADISE DR    WEST BEND, WI    
2 3502234000 S2 REAL ESTATE GROUP 5 LLC 11512 W WOODSIDE DR HALES CORNERS, WI
3 4029979100 SAM STAIR                  2925 W LINCOLN AVE  MILWAUKEE, WI    
4 4331301000 S2 REAL ESTATE GROUP       2925 W LINCOLN AVE  MILWAUKEE, WI    
5 4690309000 S2 REAL ESTATE GROUP 5 LLC 2925 W LINCOLN AV   MILWAUKEE, WI    
6 4690487000 S2 REAL ESTATE GROUP 5 LLC 2925 W LINCOLN AVE  MILWAUKEE, WI    
7 4690686000 S2 REAL ESTATE GROUP 5 LLC 2925 W LINCOLN AV   MILWAUKEE, WI    
8 4702065000 S2 REAL ESTATE             11512 W WOODSIDE DR HALES CORNERS, WI
9 4980108200 S2 REAL EST GROUP          2925 W LINCOLN AVE  MILWAUKEE, WI    

我已经编写了connect_owners_by_address函数,输入业主名称向量,返回所有共享地址的业主名称:

# 识别所有与给定名称共享地址的其他业主名称
connect_owners_by_address <- function(landlord_names){
  # 获取给定业主名下的所有地址
  addresses1 <- df %>%
    filter(OWNER_NAME_1 %in% landlord_names) %>%
    group_by(OWNER_MAIL_ADDR, OWNER_CITY_STATE) %>%
    summarise() %>%
    ungroup()
  
  # 获取这些地址关联的所有业主名称
  names.at.addresses <- df %>%
    inner_join(addresses1, by = join_by(OWNER_MAIL_ADDR, OWNER_CITY_STATE)) %>%
    group_by(OWNER_NAME_1) %>%
    summarise()
  
  names.at.addresses$OWNER_NAME_1
}

递归调用该函数可以找到更多关联业主,但需要手动重复调用直到结果不再新增:

# 第一次调用(4个匹配结果)
connect_owners_by_address("SAM STAIR")
[1] "S2 REAL EST GROUP"          "S2 REAL ESTATE GROUP"       "S2 REAL ESTATE GROUP 5 LLC" "SAM STAIR"   

# 第二次调用(5个匹配结果)
connect_owners_by_address("SAM STAIR") |>
  connect_owners_by_address()
[1] "S2 REAL EST GROUP"          "S2 REAL ESTATE"             "S2 REAL ESTATE GROUP"       "S2 REAL ESTATE GROUP 5 LLC"
[5] "SAM STAIR" 

# 第三次调用(结果不再变化)
connect_owners_by_address("SAM STAIR") |>
  connect_owners_by_address() |>
  connect_owners_by_address()
[1] "S2 REAL EST GROUP"          "S2 REAL ESTATE"             "S2 REAL ESTATE GROUP"       "S2 REAL ESTATE GROUP 5 LLC"
[5] "SAM STAIR" 

我需要把这个函数封装成一个新函数,让它自动循环调用,直到输出结果的长度和输入长度一致时停止,不知道如何用while循环实现这个逻辑。


解决方案

可以编写一个封装函数,用循环持续调用connect_owners_by_address,每次比较输入和输出的长度,直到两者相等(即没有新的业主被关联)就终止循环:

find_all_related_owners <- function(initial_names) {
  current_names <- initial_names
  repeat {
    # 调用函数获取新的关联业主
    new_names <- connect_owners_by_address(current_names)
    # 去重并排序,避免顺序或重复值影响长度判断
    current_names <- sort(unique(current_names))
    new_names <- sort(unique(new_names))
    # 如果当前结果和新结果长度一致,说明没有新增,退出循环
    if (length(current_names) == length(new_names)) {
      break
    }
    # 更新当前结果为新结果,继续循环
    current_names <- new_names
  }
  return(current_names)
}

测试验证

调用这个封装函数测试:

find_all_related_owners("SAM STAIR")
[1] "S2 REAL EST GROUP"          "S2 REAL ESTATE"             "S2 REAL ESTATE GROUP"       "S2 REAL ESTATE GROUP 5 LLC"
[5] "SAM STAIR" 

逻辑说明

  1. 初始化current_names为输入的初始业主名称
  2. 在循环中调用connect_owners_by_address获取新的关联业主列表
  3. 对当前和新列表进行去重、排序,避免因顺序或重复值导致长度判断出错
  4. 比较两者的长度:如果相等,说明没有新的业主被找到,终止循环;否则更新current_names为新列表,继续循环
  5. 最后返回最终的关联业主列表

内容的提问来源于stack exchange,提问作者John J.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 20:22:02