我有一个名单,例如['Agrajag', 'Colin', 'Deep Thought', ... , 'Zaphod Beeblebrox', 'Zarquon']
。现在我想将此列表划分为大致相同大小的子列表,以便子组的边界位于名称的第一个字母,例如AF,GL,MP,QZ,而不是A-Fe,Fi-Mo,Mu-Pra ,Pre-Z。
我只能想出一个不考虑子组大小的静态大小的分区:
import string, itertools
def _group_by_alphabet_key(elem):
char = elem[0].upper()
i = string.ascii_uppercase.index(char)
if i > 19:
to_c = string.ascii_uppercase[-1];
from_c = string.ascii_uppercase[20]
else:
from_c = string.ascii_uppercase[i/5*5]
to_c = string.ascii_uppercase[i/5*5 + 4]
return "%s - %s" % (from_c, to_c)
subgroups = itertools.groupby(name_list, _group_by_alphabet_key)
有更好的想法吗?
P.S。:这听起来有点像家庭作业,但它实际上是一个网页,其成员应该在5-10个同样大小的组中显示。
答案 0 :(得分:4)
这可能有用。我确信有一种更简单的方法......可能涉及itertools
。请注意,num_pages
仅粗略确定您实际获得的页数。
.upper()
来说明可能的小写名称。
EDIT2:以前定义letter_groups的方法效率低下;以下基于dict的代码更具可扩展性:
names = ['Agrajag', 'Colin', 'Deep Thought', 'Ford Prefect' , 'Zaphod Beeblebrox', 'Zarquon']
num_pages = 3
def group_names(names, num_pages):
letter_groups = defaultdict(list)
for name in names: letter_groups[name[0].upper()].append(name)
letter_groups = [letter_groups[key] for key in sorted(letter_groups.keys())]
current_group = []
page_groups = []
group_size = len(names) / num_pages
for group in letter_groups:
current_group.extend(group)
if len(current_group) > group_size:
page_groups.append(current_group)
current_group = []
if current_group: page_groups.append(current_group)
return page_groups
print group_names(names, num_pages)
答案 1 :(得分:1)
由于name_list
必须按groupby
排序才能正常工作,您难道不能只检查每个第N个值并以此方式构建分部吗?
right_endpoints = name_list[N-1::N]
使用"A"
作为最左端点,"Z"
作为最右端点,可以相应地构建N个分区,它们都应该具有相同的大小。
right_endpoints[0]
。right_endpoints[0]
后面的字符,下一个右端点是right_endpoints[1]
。如果其中两个right_endpoints
相同,那么您可能会遇到的问题是......
编辑示例
>>> names = ['Aaron', 'Abel', 'Cain', 'Daniel', 'Darius', 'David', 'Ellen', 'Gary', 'James', 'Jared', 'John', 'Joseph', 'Lawrence', 'Michael', 'Nicholas', 'Terry', 'Victor', 'Zulu']
>>> right_ends, left_ends = names[2::3], names[3::3]
>>> left_ends = ['A'] + left_ends
>>> left_ends, right_ends
>>> ["%s - %s" % (left, right) for left, right in zip(left_ends, right_ends)]
['A - Cain', 'Daniel - David', 'Ellen - James', 'Jared - Joseph', 'Lawrence - Nicholas', 'Terry - Zulu']