2011-02-08 10 views
7

Mam listę nazw, np. ['Agrajag', 'Colin', 'Deep Thought', ... , 'Zaphod Beeblebrox', 'Zarquon']. Teraz chcę podzielić tę listę na sublisty o podobnej wielkości, tak aby granice podgrup były na pierwszej liście nazw, np. AF, GL, MP, QZ, nie A-Fe, Fi-Mo, Mu-Pra , Pre-Z.Python: lista partycji nazw do podlist o jednakowej wielkości

mogę tylko wymyślić statycznie wielkości parition że nie bierze rozmiar podgrup pod uwagę:

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) 

lepiej pomysły?

P.S .: Może to brzmieć trochę jak zadanie domowe, ale tak naprawdę jest to strona internetowa, na której członkowie powinni być wyświetlani w 5-10 zakładkach o jednakowej wielkości.

Odpowiedz

4

Oto coś, że może działać. Czuję, że jest prostszy sposób ... prawdopodobnie z udziałem itertools. Zauważ, że num_pages tylko z grubsza określa, ile stron faktycznie otrzymasz.

EDYCJA: Whoops! Był błąd - odcinał ostatnią grupę! Poniższe dane powinny być poprawione, ale pamiętaj, że długość ostatniej strony będzie nieco nieprzewidywalna. Ponadto dodałem .upper(), aby uwzględnić możliwe małe litery.

EDIT2: poprzednia metoda definiowania grup letter_group była niewydajna; Poniższy kod oparty na dyktowaniu jest bardziej skalowalny:

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

To wydaje się działać dość dobrze z moimi prawdziwymi danymi około 500 imion. Dzięki! –

+0

Ach, dobrze - nie był pewien, czy będzie skalować. – senderle

+0

@piquadrat, dzięki za zaakceptowanie - ale zauważ błąd! Zostało to naprawione powyżej. – senderle

1

Skoro Twój name_list musi zostać posortowany, aby działał groupby, nie możesz po prostu sprawdzić każdej N-tej wartości i zbudować w ten sposób swoich podziałów?

right_endpoints = name_list[N-1::N] 

i korzystania "A" jako swojej skrajnej lewej końcowego i "Z" jako skrajnej prawej punktu końcowego, można skonstruować podziały odpowiednio N i wszystkie one powinny mieć taką samą wielkość.

  1. Pierwszy lewy punkt końcowy to "A", pierwszy prawy punkt końcowy to right_endpoints[0].
  2. Następny lewy punkt końcowy będzie znakiem po right_endpoints[0], następnym prawym końcowym punktem będzie right_endpoints[1].
  3. Itd., Aż trafisz na N-ty zakres i który ma ustawiony punkt końcowy "Z".

Problem może napotkasz co jeśli dwie z nich są takie same right_endpoints ...

edit: przykład

>>> 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

Ale chce dzielić granice początkowe, nie tylko w dowolnym miejscu. –

+0

W prawo, początkowe wyodrębnianie znaków jest pomijane, aby uprościć, ale pomysł jest wciąż taki sam. Zdobądź każdy N-ty wpis, wydobądź z niego to, co chcesz, jako definiujące punkt końcowy, i stamtąd. –

Powiązane problemy