在递归方法中向数组添加值

时间:2014-04-16 19:56:37

标签: ruby arrays recursion

方法:get_users_in_groups(groupname) 目的:获取来自组和任何嵌套组的所有成员'成员。

方法的英文翻译:

get group information
if group has members, 
    add members to users[]
end
If group has nested_groups,
    for nested_group in nested_groups
        get nested_groupname
        get_users_in_groups(nested_groupname)
    end
end

目前我在方法属性中传递users数组。但是,这似乎不是在递归方法中访问数组的正确方法。

通过递归方法将成员添加到users数组的最佳方法是什么?

我想我可能找到了解决方案。

users = []
get group information
if group has members, 
   users.concat( members[] )
end
If group has nested_groups,
    for nested_group in nested_groups
        get nested_groupname
        users.concat( get_users_in_groups(nested_groupname) )
    end
end
users.uniq

这是最好的方法吗?

很抱歉,我打算加一个!

ISC-人员 嵌套组:isc-admins,isc-teachers,isc-paras 成员:无

ISC-管理员 嵌套组:无 成员:adminone,admintwo

ISC-教师 嵌套组:加速教师 成员:teacherone,teachertwo

ISC-第 嵌套组:无 成员:paraone,paratwo

加速教师 嵌套组:无 成员:spedteacherone,spedteachertwo

所以我的方法查找isc-staff,看到它有isc-admins,isc-teachers和isc-paras但没有成员,它需要在isc-admins,isc-teachers和isc-paras上运行。 当它在isc-admins上运行时,它应该将成员添加到用户[] 当它在isc-teachers上运行时,它应该将成员添加到users []并通过sped-teachers运行自己

此信息不存储在数组中,必须从LDAP中提取。

这有足够的信息吗?

结构与

类似
{
 group_name: 'isc-staff',
 nested_groups: [
                 {
                  group_name: 'isc-admins',
                  members: ['adminone', 'admintwo']
                 },
                 {
                  group_name: 'isc-teachers',
                  members: ['teacherone', 'teachertwo'],
                  nested_groups: [
                                  {
                                   group_name: 'sped-teachers',
                                   members: ['spedteacherone']
                                  }
                                 ]
                 },
                 {
                  group_name: 'isc-paras',
                  members: ['paraone', 'paratwo']
                 }
 ]
}

结果应该是:

['adminone','admintwo','teacherone','teachertwo','spedteacherone','paraone','paratwo']

3 个答案:

答案 0 :(得分:0)

我的解决方案很普遍。您的结构可以是数组或散列,递归地包含任何深度的数组,散列和文字。我假设你想要的值是数组中的字符串,并且所有数组都不包含字符串或只包含字符串(尽管那些不包含字符串的字符串可能包含嵌套的字符串数组,可以找到它们。)

<强>代码

def getem(e,a=[])
  case e
  when Array
    case e.first
    when String
      e.each { |f| a << f }
    else
      e.each do |f|
        case f
        when Array, Hash
          getem(f,a)
        end
      end
    end
  when Hash
    e.each { |_,v| getem(v,a) }
  end
  a
end     

示例

h = {
 group_name: 'isc-staff',
 nested_groups:
   [
     {
        group_name: 'isc-admins',
        members: ['adminone', 'admintwo']
     },
     {
        group_name: 'isc-teachers',
        members: ['teacherone', 'teachertwo'],
        nested_groups:
          [{
              group_name: 'sped-teachers',
              members: ['spedteacherone']
          }]
     },
     {
        group_name: 'isc-paras',
        members: ['paraone', 'paratwo']
     }
   ]
}

getem(h)
  #=> ["adminone", "admintwo", "teacherone", "teachertwo",
  #   "spedteacherone", "paraone", "paratwo"]

(请注意,您在示例哈希中犯了几个小错误。)

<强>解释

    getem是数组或散列时,会调用
  • e。返回值是数组a,在首次调用getem时默认为空数组。

  • 我们使用case语句来测试对象的类。这是有效的,因为案例使用Object#===而不是==来确定truefalse

  • 如果getem的第一个参数是一个数组,我们看看第一个元素是否是一个字符串。如果是,我们假设所有元素都是字符串,并将它们添加到数组a。否则,我们递归调用getem作为数组或散列的每个元素。

  • 如果getem的第一个参数是散列,我们递归调用getem作为数组或散列的每个值。 (由于我们不在块中使用散列键,因此我们可以编写|_v|而不是|k,v|)。

答案 1 :(得分:0)

假设您的数据结构是带有符号键的哈希,一个简单的递归函数可以解决这个问题:

def all_group_members group
  members = []
  members.concat group[:members] if group[:members]
  if group[:nested_groups]
    group[:nested_groups].each { |g| members.concat all_group_members(g) }
  end
  members
end

答案 2 :(得分:0)

根据我过去几天对递归查询的了解,我提出了这种方法。这有用吗?

def self.get_users_in_group(groupname)
            users = []
            if exists?(groupname)
                params = [
                            "GroupMembership",
                            "NestedGroups"
                        ]
                DSQuery.generate_dscl("read","/Groups/#{groupname}",params)
                output = DSQuery.run
                # Add members of group to users array.
                if output.has_key?('dsAttrTypeStandard:GroupMembership')
                    users.concat(output['dsAttrTypeStandard:GroupMembership'])
                end
                # if group contains nested groups,
                # get_users_in_group for each nested group and add to users array.
                if output.has_key?('dsAttrTypeStandard:NestedGroups')
                    output['dsAttrTypeStandard:NestedGroups'].each do |generate_dscldUID|
                        results = find('GeneratedUID',generate_dscldUID)
                        if !results.empty?
                            result = results[0]
                            length_of_nested_group_name = result.index("\t") - "\t".length
                            nested_group_name = result.slice(0..length_of_nested_group_name)
                            users.concat( get_users_in_group(nested_group_name) )
                        end
                    end
                end
            end
            users.uniq
        end