Есть ли стандартное имя для этой функции?

Как бы вы назвали функцию, которая принимает список и функцию и возвращает True, если применение функции ко всем элементам дает одинаковый результат?

def identical_results(l, func):
    if len(l) <= 1: return True
    result = func(l[0])
    for el in l[1:]:
        if func(el) != result:
            return False
    return True

Есть ли красивое общепринятое название для этой штуки? Бонус, если вы можете реализовать менее неуклюжим способом.


person itsadok    schedule 08.10.2009    source источник


Ответы (5)


В .NET ближайшим является Array.TrueForAll.

Может быть, SameForAll больше подходит для этой функции?

person Jon Seigel    schedule 08.10.2009
comment
О, спасибо: SameForAll действительно лучшее предложение, которое я когда-либо слышал - person Dario; 08.10.2009

Пока не слышал о специальном имени для этого (несколько похожем на Forall, но не совсем). IdenticalResults кажется нормальным, так что (Джон Сейгель предложил SameForAll, тоже неплохо)

Дополнительно: так можно было бы реализовать это в Haskell, используя функцию all (TrueForall в .NET)

ident [] = True
ident (x:xs) = all (== x) xs

sameForAll f = ident . map f

И Питон:

def idents(f, list):
    if len(list) <= 1:
        return True
    else:
        let fx0 = f(list[0])
        return all(( f(x) == fx0 for x in list[1:] ))
person Dario    schedule 08.10.2009
comment
это в значительной степени проверка того, постоянна ли функция в домене. - person nlucaroni; 08.10.2009
comment
Не уверен насчет Haskell, но python, кажется, возвращает True, если все элементы идентичны. Это здорово, потому что теперь я могу вызвать idents(map(f, list)) для реализации SameForAll. Исправьте свой код, чтобы я мог дать вам голос... - person itsadok; 08.10.2009
comment
Ой, я просто забыл применить f ;-) - person Dario; 08.10.2009
comment
О, я думаю, что я получаю Haskell, и вы должны сделать либо \el -> f el == f x, либо \el -> el = x, а затем sameforall = idents map (правильно?) - person itsadok; 08.10.2009
comment
@ Дарио, но если вы сделаете это с помощью map, вы вызовете f только один раз для первого элемента. - person itsadok; 08.10.2009
comment
Haskell все равно кеширует это. Тем не менее, теперь это еще круче ;-) - person Dario; 08.10.2009

Пока не могу придумать хорошее имя, но это делает то же самое:

def identical_results(l, func):
    return len(set(map(func, l))) <= 1
person balpha    schedule 08.10.2009
comment
Очень лаконичный код, но неэффективный, поскольку для создания набора требуется O(n log n), тогда как для алгоритма достаточно O(n). - person Dario; 08.10.2009
comment
@Дарио: Да, если это проблема. - person balpha; 08.10.2009
comment
Ага, правильная мысль балфа. reduce() объединит результаты без создания набора: def идентичные_результаты(l, func): return reduce(lamdba x,y: x and y, map(func, l)) Так как это map+reduce, это также очень масштабируемо (см. статью Google Mapreduce). - person Lee B; 08.10.2009
comment
@Lee B: То, что вы предлагаете, не имеет такой же функциональности. - person balpha; 08.10.2009
comment
В Python наборы реализованы как хеш-таблицы, а не как двоичные деревья, поэтому создание набора — это O(n), а не O(n log n). - person Roberto Bonvallet; 11.10.2009
comment
@Roberto Bonvallet: я этого не знал. Согласуется ли это между реализациями? В любом случае, я бы беспокоился о производительности такой функции только тогда, когда вы знаете (читай: можете доказать), что это проблема. При создании такой функции, как identical_results(), при условии, что она вызывается для относительно небольших списков и не слишком часто, любое время, потраченное на размышления о производительности, тратится впустую. Особенно в случае (как здесь), когда у вас есть очень четко определенные входы и выходы, что упрощает последующую реализацию оптимизированной версии, если возникнет такая необходимость. - person balpha; 11.10.2009

идентичные_результаты звучит как разумное имя для меня.

person b.roth    schedule 08.10.2009

Я разместил это в комментарии выше, но форматирование испортилось, так что вот еще раз для ясности:

def identical_results(l, func):
    return reduce(lamdba x,y: x and y, map(func, l))
person Lee B    schedule 08.10.2009
comment
Я думаю, у вас есть правильная идея, но сейчас вы внедрили TrueForAll вместо SameAll - person itsadok; 08.10.2009
comment
Правильно. Я думал, что функция может сделать всю работу (и она может), но, вероятно, было бы лучше, если бы сокращение проверяло массив и добавляло только новые значения. Тем не менее, это в значительной степени будет набором, как предложено выше. - person Lee B; 09.10.2009