2012-05-24 2 views
6

Учитывая список входных данных (допустим, это просто целые числа) и список функций (и эти функции принимают целое число и возвращают True или False).Алгоритм поиска, но для функций

Мне нужно взять этот список ввода и посмотреть, вернет ли какая-либо функция в списке True для любого значения в списке.

Есть ли способ сделать это быстрее, чем O (N^2)

Прямо сейчас, что у меня есть

for v in values: 
    for f in functions: 
     if f(v): 
      # do something to v 
      break 

быстрее методы?

+0

функции чисты, я надеюсь? Знаете ли вы что-нибудь еще о них? –

+0

"return True для любого значения в списке" ... Означает ли это, что функция возвращает true для каждого значения ... или только одно значение? – sukunrt

+1

Это может быть несколько быстрее, чем 'any (f (v) для v в значениях для f в функциях)', но не меньше, чем O (n_functions * n_values). –

ответ

10

Без дополнительной информации о функциях, результаты возможных вызовов функций должны считаться независимыми друг от друга, поэтому нет более быстрого способа, чем проверка их всех.

Вы можете написать это немного более сжато, хотя:

any(f(v) for v in values for f in functions) 

встроенную функцию any() также короткого замыкания, так же, как ваш исходный код.

Edit: Получается, что желаемый эквивалент был бы

all(any(f(v) for f in functions) for v in values) 

Смотрите комментарии для обсуждения.

3

Нет, нет более быстрого пути. O (m * n) - предел. Если бы у вас было больше информации о функциях, вы могли бы побить это, но в общем случае нет.

2

Если вы знаете больше о функциях или значениях, вы можете сделать то, что делает обычная поисковая система, - примените некоторую индексацию по списку значений, для которой требуется только один проход.

EDIT:

Вот подход с any(), который работает для этого использования.

for v in values: 
    if any(f(v) for f in functions): 
     #do something to v 
2

Вы не можете сделать лучше, чем O(nm) лишь их запросов и без каких-либо упрощающих предположений о функциях под рукой.

Это потому, что доказательство отсутствия таких функций требует, чтобы вы доказали, что для любого целого и любой функции результатом запроса является False.

Чтобы доказать это, вы не можете сделать меньше, чем выполнять все запросы, потому что ваш state space является O(2^nm) и запрос только половины пространства состояний, так что вам нужно O(log_2(2^nm)) = O(nm) запросы, чтобы уменьшить пространство состояний для решения «каждая функция возвращает ложь для каждого целого числа ".

1

Это на самом деле не O (п), но это спасает вас от итерации функции каждый раз:

#combine all funcs into one with `or` 
newFunc = reduce(lambda f,g: (lambda x: f(x) or g(x)), funcs) 

#cleaner than for, i think 
satisfied = any(map(newFunc, values)) 

Обсуждая ли вложенные лямбды являются вещим это совсем другой история, но я склонен думать в функциональном при рассмотрении списков функций.

+0

Интересная идея. Обратите внимание, что в Python (2.7) 'any()' является глобальным встроенным, а не классным методом списка. –

+0

это не будет короткое замыкание, правда? –

+0

@MattLuongo спасибо за указание, что вне, исправлено. – phg

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