2011-02-08 44 views
7

Tôi có danh sách tên, ví dụ: ['Agrajag', 'Colin', 'Deep Thought', ... , 'Zaphod Beeblebrox', 'Zarquon']. Bây giờ tôi muốn phân vùng danh sách này thành các danh sách phụ có kích thước bằng nhau, để ranh giới của các nhóm con ở chữ cái đầu tiên của các tên, ví dụ: AF, GL, MP, QZ, không phải A-Fe, Fi-Mo, Mu-Pra , Pre-Z.Python: danh sách phân vùng tên thành các danh sách con có kích thước bằng nhau

tôi chỉ có thể đưa ra một parition tĩnh cỡ mà không mất kích thước của các phân nhóm vào tài khoản:

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) 

Bất kỳ ý tưởng tốt hơn?

P.S .: điều này nghe có vẻ hơi giống với bài tập về nhà, nhưng thực tế là dành cho trang web nơi các thành viên sẽ được hiển thị trong 5-10 tab có nhóm có kích thước bằng nhau.

Trả lời

4

Dưới đây là một cái gì đó mà có thể làm việc. Tôi cảm thấy chắc chắn có một cách đơn giản hơn mặc dù ... có thể liên quan đến itertools. Lưu ý rằng num_pages chỉ gần xác định số lượng trang bạn thực sự sẽ nhận được.

EDIT: Rất tiếc! Có một lỗi - nó đã bị cắt khỏi nhóm cuối cùng! Dưới đây nên được khắc phục, nhưng lưu ý rằng độ dài của trang cuối cùng sẽ không thể đoán trước được. Ngoài ra, tôi đã thêm .upper() để tính các tên chữ thường có thể.

EDIT2: Phương pháp xác định nhóm letter_group trước đây không hiệu quả; mã dựa trên dict dưới đây có thể mở rộng hơn:

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) 
+0

Điều đó dường như hoạt động tốt với dữ liệu thực của tôi về 500 Tên. Cảm ơn! –

+0

Ah, tốt - không chắc liệu nó có mở rộng không. – senderle

+0

@piquadrat, cảm ơn vì đã chấp nhận - nhưng hãy lưu ý lỗi! Nó được cố định ở trên. – senderle

1

name_list của bạn phải được sắp xếp để groupby hoạt động, bạn không thể chỉ kiểm tra mọi giá trị Nth và xây dựng các bộ phận theo cách đó?

right_endpoints = name_list[N-1::N] 

Và sử dụng "A" như endpoint tận cùng bên trái của bạn và "Z" như thiết bị đầu cuối ngoài cùng bên phải, bạn có thể xây dựng các đơn vị N cho phù hợp và tất cả họ cần phải có cùng kích thước.

  1. Vì vậy, điểm cuối bên trái đầu tiên sẽ là "A", điểm cuối bên phải đầu tiên sẽ là right_endpoints[0].
  2. Điểm cuối bên trái tiếp theo sẽ là ký tự sau right_endpoints[0], điểm cuối bên phải tiếp theo sẽ là right_endpoints[1].
  3. Vv, cho đến khi bạn nhấn vào phạm vi thứ N và có điểm cuối là "Z".

Vấn đề bạn có thể gặp là gì nếu hai trong số các right_endpoints đều giống nhau ...

chỉnh sửa: dụ

>>> 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'] 
+0

Nhưng anh ấy muốn phân chia ở ranh giới ký tự ban đầu, không chỉ ở bất kỳ đâu. –

+0

Phải, trích xuất ký tự ban đầu được bỏ ra để đơn giản hóa, nhưng ý tưởng vẫn như cũ. Nhận mọi mục nhập Nth, trích xuất những gì bạn muốn làm điểm cuối của bộ giải mã và thoát khỏi đó. –

Các vấn đề liên quan