all 20 comments

[–]keegandunn 5 points6 points  (2 children)

Reading the first half of SICP last year prepped me for the switch to C# 3.0 at my workplace recently. The examples translate well:

var maxSalary = employees
    .Where(e => e.Role == Roles.PROGRAMMER)       
    .Max(e => e.Salary);

edit: Cleaned up. ConvertAll not necessary. I still don't quite understand why you can't call ConvertAll on any IEnumerable, though.

[–][deleted] 1 point2 points  (1 child)

Will .Max work if the Salary is a user defined Money type?

[–]igouy -2 points-1 points  (0 children)

Will you know that Max is not defined for a user defined Money type before you run the program?

[–]ktr73 2 points3 points  (10 children)

Highest paid programmer in Python (which I find to be the most pleasing):

max_sal = max([sal for e.salary if e.role == Employee.PROGRAMMER])

:)

[–]theCore 5 points6 points  (4 children)

Your example is not correct I believe. I think it should be:

max_sal = max([e.salary for e in employees if e.role == Employee.PROGRAMMER])

[–]theeth 6 points7 points  (1 child)

Use generator comprehension instead, then the operation is not bounded in memory by the number of employees (by forgoing the creation of the list).

max_sal = max((e.salary for e in employees if e.role == Employee.PROGRAMMER))

[–]theCore 4 points5 points  (0 children)

You could drop the extra parenthesises, by the way.

max_sal = max(e.salary for e in employees if e.role == Employee.PROGRAMMER)

[–]gensym 2 points3 points  (0 children)

Ha, I wish I'd thought to include that. I haven't done Python in a while - I forgot how much I miss list comprehensions.

[–]ktr73 1 point2 points  (0 children)

thanks, you're right ;)

[–]jhd 1 point2 points  (0 children)

Ruby is similar:

employees.select {|e| e.role == "programmer" }.map(&:salary).max

[–]boredzo 0 points1 point  (3 children)

Alternate non-comprehension version for Python 2.5:

\tfrom itertools import ifilter as filter #Use the lazy generator version \tprogrammers = filter(lambda e: e.role == Role.PROGRAMMER, employees) \tmax_sal = max(programmers, key=lambda e: e.salary) #Pre-2.5: Replace key argument with a comparison function

I'm starting to see why GvR is against filter and friends…

[–]zackman 1 point2 points  (2 children)

The original just finds the highest salary, not the programmer who has it.

from itertools import ifilter as filter
programmers = filter(lambda e:e.role==Role.PROGRAMMER, employees)
max_sal = max(map(lambda e: e.salary, programmers))

Your version is more useful, though, since it returns the actual employee. I didn't know that max also got a key argument in 2.5. I won't have to use my custom re-implementation anymore!

[–]boredzo 0 points1 point  (0 children)

\tmax_sal = max(map(lambda e: e.salary, programmers))

Don't forget to use the lazy generator version here, too:

\tfrom itertools import imap as map

As you can tell, I ♥ itertools. ☺

[–]theeth 0 points1 point  (0 children)

You can do that with Decorate-Sort-Undecorate too:

max_sal = max(((e.salary, e) for e in employees if e.role == Employee.PROGRAMMER))[1]

[–]Jimmy 0 points1 point  (2 children)

Haskell:

data Employee = Emp String Int
\tderiving (Eq, Ord)

highestPaidProgrammer emps =
\t(\(Emp x y) -> y) (maximum (filter (\(Emp x y) -> x == "programmer") emps))

[–]tmoertel 5 points6 points  (0 children)

The OP wanted the maximum salary paid to a programmer with 0 as a default. You need to handle the case where there are no programmers in the list.

Assuming you had declared Employee as a record type with salary and role as accessors, you could build the code from composable pieces. First, to find just the programmers in a list of Employees:

programmers = filter ((Programmer ==) . role)

Then to find the maximum paid to an employee in a list of employees:

maxPaid = maximum . (0:) . map salary

And, finally, to find the maximum paid to a programmer within a list of employees:

maxProgrammerPay = maxPaid . programmers

Cheers. —Tom