在字符串列表中查找部分字符串 - python

时间:2009-07-07 22:56:02

标签: python regex list

我正在尝试检查用户是否是Active Directory组的成员,我有:

ldap.set_option(ldap.OPT_REFERRALS, 0)
try:
  con = ldap.initialize(LDAP_URL)
  con.simple_bind_s(userid+"@"+ad_settings.AD_DNS_NAME, password)
  ADUser = con.search_ext_s(ad_settings.AD_SEARCH_DN, ldap.SCOPE_SUBTREE, \  
           "sAMAccountName=%s" % userid, ad_settings.AD_SEARCH_FIELDS)[0][1]
except ldap.LDAPError:
  return None

ADUser返回字符串列表:

{'givenName': ['xxxxx'],
 'mail': ['xxxxx@example.com'],
 'memberOf': ['CN=group1,OU=Projects,OU=Office,OU=company,DC=domain,DC=com',
              'CN=group2,OU=Projects,OU=Office,OU=company,DC=domain,DC=com',
              'CN=group3,OU=Projects,OU=Office,OU=company,DC=domain,DC=com',
              'CN=group4,OU=Projects,OU=Office,OU=company,DC=domain,DC=com'],
 'sAMAccountName': ['myloginid'],
 'sn': ['Xxxxxxxx']}

当然,在现实世界中,群组名称冗长且结构各异,用户将属于数十个或数百个群体。

如果我将组列表作为ADUser.get('memberOf')[0]获取,那么检查主列表中是否存在单独列表的任何成员的最佳方法是什么?

例如,检查列表为['group2', 'group16'],我想得到一个真/假答案,确定主列表中是否存在任何较小列表。

2 个答案:

答案 0 :(得分:2)

如果您提供的格式示例有点可靠,例如:

import re
grps = re.compile(r'CN=(\w+)').findall

def anyof(short_group_list, adu):
  all_groups_of_user = set(g for gs in adu.get('memberOf',()) for g in grps(gs))
  return sorted(all_groups_of_user.intersection(short_group_list))

您将['group2', 'group16']列表作为第一个参数传递,ADUser dict作为第二个参数;这将返回用户所属的short_group_list中的组中按字母顺序排序的列表(可能为空,表示“无”)。

一个bool可能没那么快,但是,如果你坚持,将函数的第二个语句更改为:

  return any(g for g in short_group_list if g in all_groups_of_user)

可能会在“真实”情况下节省一定的时间(因为any短路)但我怀疑不是在“假”情况下(无论如何必须遍历整个列表)。如果您关心性能问题,最好的方法是对数据的可能性进行基准测试,这对您的用例来说是真实的!

如果性能还不够好(如你所说,bool yes / no就足够了),请尝试颠倒循环逻辑:

def anyof_v2(short_group_list, adu):
  gset = set(short_group_list)
  return any(g for gs in adu.get('memberOf',()) for g in grps(gs) if g in gset)

any的短路能力可能在这里证明更有用(至少在“真实”的情况下,再次 - 因为,再次,如果没有检查所有的话,就没有办法给出“错误的”结果无论如何可能性! - )。

答案 1 :(得分:1)

解析组列表后,可以使用set intersection(& operator)。例如:

> memberOf = 'CN=group1,OU=Projects,OU=Office,OU=company,DC=domain,DC=com'

> groups = [token.split('=')[1] for token in memberOf.split(',')]

> groups
['group1', 'Projects', 'Office', 'company', 'domain', 'com']

> checklist1 = ['group1', 'group16']

> set(checklist1) & set(groups)
set(['group1'])

> checklist2 = ['group2', 'group16']

> set(checklist2) & set(groups)
set([])

请注意,对集合的条件评估与列表和元组的作用相同。如果集合中有任何元素,则为True,否则为False。因此,"if set(checklist2) & set(groups): ..."将不会执行,因为在上面的示例中条件求值为False(对于checklist1测试,情况相反)。

另见:

http://docs.python.org/library/sets.html