views:

269

answers:

5

What would you name a function that takes a list and a function, and returns True if applying the function to all elements gives the same result?

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

Is there a nice generally accepted name for this thing? Bonus if you can implement in a less clunky fashion.

+4  A: 

In .NET, the closest is Array.TrueForAll.

Maybe SameForAll would be more appropriate for this function?

Jon Seigel
@Dario: Read again. I edited after my last comment.
Jon Seigel
Oh, thx: SameForAll is indeed the best proposition I heard yet
Dario
A: 

identical_results sounds like a reasonable name to me.

Bruno Rothgiesser
+1  A: 

Can't think of a good name so far, but this one does the same:

def identical_results(l, func):
    return len(set(map(func, l))) <= 1
balpha
Very concise code, but inefficient since creating a set requires O(n log n) whereas the algorithm should just need O(n).
Dario
@Dario: True, if that's an issue.
balpha
Yep, right idea balpha. reduce() will merge the results without creating a set:def identical_results(l, func): return reduce(lamdba x,y: x and y, map(func, l))Since it's map+reduce, this is highly scaleable too (see Google's Mapreduce paper).
Lee B
@Lee B: What you're proposing does not have the same functionality.
balpha
In Python, sets are implemented as hash tables, not as binary trees, so set creation is O(n), not O(n log n).
Roberto Bonvallet
@Roberto Bonvallet: I didn't know that. Is that consistent among implementations? Anyhow, I'd worry about performance of such a function only when you know (read: can prove) that it's an issue. When creating a function like `identical_results()`, assuming it's being called on relatively small lists and not too often, any time spent on thinking about performance is wasted. Especially in a case (like here) where you have very well-defined inputs and outputs, making it easier to later implement an optimized version, should the need arise.
balpha
+4  A: 

Havn't heard about a special name for this yet (somewhat similar to Forall, but not exactly). IdenticalResults seems okay so (Jon Seigel proposed SameForAll, also quite nice)

Additionally: That's the way one could implement this in Haskell using the all function (TrueForall under .NET)

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

sameForAll f = ident . map f

And Python:

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:] ))
Dario
it's pretty much testing if the function is constant over a domain.
nlucaroni
Not sure about the Haskell one, but the python one seems to return True if all items are identical. That's cool, because now I can call `idents(map(f, list))` to implement SameForAll. Fix up your code so I can give you an upvote...
itsadok
Oops, I just forgot to apply f ;-)
Dario
Oh, I think I'm getting the Haskell one, and you should either do `\el -> f el == f x` or `\el -> el = x` and then `sameforall = idents map` (right?)
itsadok
@Dario but if you do it with `map` you only call f once on the first element.
itsadok
Haskell will cache this anyway. Nevertheless now it's even cooler ;-)
Dario
A: 

I posted this in a comment above, but the formatting got messed up, so here it is again for clarity:

def identical_results(l, func):
    return reduce(lamdba x,y: x and y, map(func, l))
Lee B
I think you have the right idea, but as it is now, you've implemented TrueForAll instead of SameAll
itsadok
right. I was thinking the function could do all the work (and it can), but it probably would be nicer if reduce checked an array and only added new values. That pretty much would be a set anyway though, like balpha suggested above.
Lee B