Ruby 从哈希数组中排除特定数据

Ruby exclude specific data from array of hashes

我得到了哈希和哈希数组的响应:

"id"=>67547,
 "description"=>"project",
 "actors"=>
  [
    {"id"=>123,
    "displayName"=>"John Doe",
    "type"=>"atlassian-user-role-actor",
    "name"=>"john.doe",
    "actorUser"=>{"accountId"=>"some_id"}},
   {"id"=>456,
     "displayName"=>"Chris Sth",
     "type"=>"atlassian-user-role-actor",
     "name"=>"chris.sth",
     "actorUser"=>{"accountId"=>"some_id"}},
   {"id"=>789,
     "displayName"=>"Testing Name",
     "type"=>"atlassian-user-role-actor",
     "name"=>"testing.name",
     "actorUser"=>{"accountId"=>"some_id"}},
  ]

我需要的是提取每个 hash['actors'] 的名称并将其转换为电子邮件地址。问题是我需要跳过定义为 EXCLUDED_NAMES

的名称
EXCLUDED_NAMES = %w[
  chris.sth
  removed1258986304
  john.doe
  other.names
].freeze

private_constant :DEFAULT_EXCLUDED_NAMES

我正在尝试类似下面的内容,但仍然得到所有名称:

def setup_email
  dev_role['actors'].map do |user|
    if user.include?(EXCLUDED_NAMES)
      user.delete
    else
      "#{user['name']}@example.com"
    end
  end
end

如果dev_role['actors']是这样的:

  [
    {"id"=>123,
    "displayName"=>"John Doe",
    "type"=>"atlassian-user-role-actor",
    "name"=>"john.doe",
    "actorUser"=>{"accountId"=>"some_id"}},
   {"id"=>456,
     "displayName"=>"Chris Sth",
     "type"=>"atlassian-user-role-actor",
     "name"=>"chris.sth",
     "actorUser"=>{"accountId"=>"some_id"}},
   {"id"=>789,
     "displayName"=>"Testing Name",
     "type"=>"atlassian-user-role-actor",
     "name"=>"testing.name",
     "actorUser"=>{"accountId"=>"some_id"}},
  ]

那么可以肯定each块中的user是一个Hash对象:

{
  "id"=>123,
  "displayName"=>"John Doe",
  "type"=>"atlassian-user-role-actor",
  "name"=>"john.doe",
  "actorUser"=>{"accountId"=>"some_id"}
}

所以,做 user["name"],应该产生:"john.doe"

现在,我们有了一个排除列表 EXCLUDED_NAMES,我们可以像这样使用 include?

EXCLUDED_NAMES.include?(user["name"])
=> # true if the name is in the EXCLUDED_NAMES

因此,您只需要对代码进行少量更改即可解决此问题:

def setup_email
  dev_role['actors'].map do |user|
    if EXCLUDED_NAMES.include?(user["name"])
      user.delete
    else
      "#{user['name']}@example.com"
    end
  end
end

但是有一个问题,user.delete 无法工作,因为它需要一个应该是散列对象键的参数。

这可以通过使用 rejectselect 来解决(更改为 reject 因为它看起来更好):

def setup_email
  dev_role['actors'].reject do |user|
    EXCLUDED_NAMES.include?(user["name"])
  end.map{ |user| user["name"] }
end

方法的本质似乎是返回一个array/list,所以我坚持认为这种方法的名称应该是复数:setup_emails.

您可以获得一组有效的电子邮件:

emails = dev_role['actors'].map do |user|
  "#{user['name']}@example.com" unless EXCLUDED_NAMES.include?(user['name'])
end

数组将只包含'testing.name@example.com'

我会根据演员姓名创建查找哈希。然后检索不在 EXCLUDED_NAMES.

中的值

当演员可以包含重名时:

actors = dev_role['actors'].group_by { |actor| actor['name'] }
actors = actors.values_at(*actors.keys - EXCLUDED_NAMES).flatten(1)

当演员不能包含重名时:

actors = dev_role['actors'].to_h { |actor| [actor['name'], actor] }
actors = actors.values_at(*actors.keys - EXCLUDED_NAMES)

然后:

emails = actors.map { |actor| "#{actor['name']}@example.com" }

您也可以使用 Array#reject/Array#map 组合来解决此问题:

emails = dev_role['actors']
         .reject { |actor| EXCLUDED_NAMES.include?(actor['name']) }
         .map { |actor| "#{actor['name']}@example.com" }

使用较大的 EXCLUDED_NAMES 数组时,上面的代码可能会变慢。

dev_role=dev_role.to_hash
actors=dev_role["actors"]
for each_actor in actors
    if EXCLUDED_NAMES.include?(each_actor["name"])==false
        p "#{each_actor['name']}@example.com"
    end
end