2014-02-08 3 views
1

Есть ли определенный рецепт для разбиения списка в соответствии с некоторым предикатом? То, что я хочу сделать, похоже на группу itertools, но предикат будет некоторой произвольно сложной функцией (а не просто ключом). Например, представьте себе список студентов, и у каждого ученика есть список курсов, и я хочу сгруппировать по тем, у кого есть общие курсы. Так что это было бы что-то вроде:У python есть функция partition_by?

def coursework_intersection(a,b): 
    return set(a['courses']).intersection(b['courses']) 

list_of_lists = partition_by(coursework_intersection, students) 
+0

Я не думаю, что эта функция написана на Python сама по себе, но не должно быть слишком сложно сделать ... Предполагая, что вы делаете «ученик» классом. – KnightOfNi

+0

Ваш вопрос для меня не имеет смысла. Предикат - это функция, возвращающая логическое значение. Таким образом, ваша функция не является предикатом! Можете ли вы привести пример ввода/ожидаемого вывода? – hivert

+0

возвращает true-y или false-y в зависимости от того, установлено ли пересечение или нет. пустое множество - false-y. – Kevin

ответ

2

Если вы хотите, что говорит Joran в комментариях, то это по своей сути Omega (п^2) в худшем случае время работы, потому что это размер производства в худшем случае (когда coursework_intersection всегда возвращает true). Так что давайте просто стиснуть зубы:

def associated_with(func, seq): 
    for item in seq: 
     yield item, (other for other in seq if func(item, other)) 

Обратите внимание, что вход представляет собой последовательность, а не итератора, так как это алгоритм многоходовых.

Это может быть оптимизировано для вызова func в два раза меньше, если нам разрешено предположить, что это симметричная функция, хотя стоимость больше использования памяти. Она также может быть оптимизирована немного в однострочник return ((item, (other for other in seq if func(item, other))) for item in seq), но я сужу, что не самый читаемый способ ввести код ;-)

1
from collections import defaultdict 

def group_by_classes(students): 
    result = defaultdict(list) 
    for student in students: 
     result[set(student["courses"])].append(student) 
    return result 

, который приведет в списке студентов для каждого уникального набора классов (т.е. каждая занятая вершина гиперкуба класса).

Смежные вопросы