Re: How is max supposed to work, especially key.

2014-12-04 Thread Terry Reedy

On 12/4/2014 5:35 AM, Albert van der Horst wrote:


I agree that it is a useful function and that it is doing
the right thing. What is wrong is the name.
I refer to the fact that it is not returning the maximum.
It returns the iterator value that leads to the maximum.
A function that doesn't return a maximum shouldn't be called
maximum.


The key function serves the same purpose as with sort.  It define a 
custom ordering of items, not the values returned.  'x < y' is defined 
as key(x) < key(y), where the comparison of keys uses the standard (and 
for numbers, natural) built-in ordering.  So max returns the max value 
according to the order you define with the key function.  The default 
key is the identity function, so the default order is the builtin order.


--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread random832
On Thu, Dec 4, 2014, at 05:09, Albert van der Horst wrote:
> So in that case max doesn't return the maximum (True), but instead
> something else.

If you want to find the "largest" item in a list of of strings, sorted
case-insensitively, you might use str.lower or locale.strxfrm as the key
function. If two strings are case-insensitively identical, using
str.lower will return an arbitrary one (or maybe the first or last found
in the original list), using locale.strxfrm will return the one that is
in uppercase in the first position where they are different. But you
don't want it to return the all-lowercase version (or the messy binary
thing returned by strxfrm), you want it to return the string from the
original list.

Think of it this way: the key function returns a proxy object whose
comparison operators compare according to the relationship you want to
compare the originals by. Bool does not make a good proxy object.

If you want to use the original as a tiebreaker, you might use lambda x:
(str.lower(x), x).

A key function is supposed to be a function that will always return the
same result on the same input, so if you want to know "the maximum"
[i.e. the actual key value that was compared by the max function] you
can simply apply it again on the result.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Jussi Piitulainen
Steven D'Aprano writes:
> Jussi Piitulainen wrote:
> 
> > Would you also want sorted called something else when used with a
> > key?  Because it doesn't produce a sorted list of the keys either:
> > 
> >   >>> data = ("short", "long", "average")
> >   >>> sorted(data, key=len)
> >   ['long', 'short', 'average']
> >   >>> max(data, key=len)
> >   'average'
> 
> I agree with the point you are making, but I disagree with the
> wording you use. The result of calling sort() with key=len *is*
> sorted. It is sorted by length of the word.

It's sorted but it's not a list of the keys. That seemed to be a point
of contention about naming max-with-key max: it doesn't return a key.

> Same for calling max() with a key. The result is still the maximum
> value.  The difference is how you decide which of two elements is
> greater:
> 
> max(list_of_foods, key=calories)
> max(list_of_foods, key=weight)
> max(list_of_foods, key=cost)
> 
> That is three different ways to decide which is the maximal food in
> the list: by number of calories, by weight, or by cost.

Yes. I don't see any disagreement between us.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Steven D'Aprano
Albert van der Horst wrote:

> I agree that it is a useful function and that it is doing
> the right thing. What is wrong is the name.
> I refer to the fact that it is not returning the maximum.
> It returns the iterator value that leads to the maximum.

That is incorrect. It returns the maximum value, that is, the value greater
than all the other values. What is different is the way "this value is
greater than that value" is tested for the purposes of calculating this
maximum.

> A function that doesn't return a maximum shouldn't be called
> maximum.

Naturally. But this does calculate the maximum, according to the given key
function.


-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Steven D'Aprano
Jussi Piitulainen wrote:


> Would you also want sorted called something else when used with a key?
> Because it doesn't produce a sorted list of the keys either:
> 
>   >>> data = ("short", "long", "average")
>   >>> sorted(data, key=len)
>   ['long', 'short', 'average']
>   >>> max(data, key=len)
>   'average'

I agree with the point you are making, but I disagree with the wording you
use. The result of calling sort() with key=len *is* sorted. It is sorted by
length of the word.

Same for calling max() with a key. The result is still the maximum value.
The difference is how you decide which of two elements is greater:

max(list_of_foods, key=calories)
max(list_of_foods, key=weight)
max(list_of_foods, key=cost)


That is three different ways to decide which is the maximal food in the
list: by number of calories, by weight, or by cost.




-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Peter Otten
Albert van der Horst wrote:
> I agree that it is a useful function and that it is doing
> the right thing. What is wrong is the name.
> I refer to the fact that it is not returning the maximum.
> It returns the iterator value that leads to the maximum.
> A function that doesn't return a maximum shouldn't be called
> maximum.

But a maximum is often ambiguous. What is max(people), the oldest, tallest, 
or richest person? The key argument is a convenient way to disambiguate.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Peter Otten
Albert van der Horst wrote:

> In article ,
> Peter Otten  <__pete...@web.de> wrote:
>>Albert van der Horst wrote:
>>
>>> In the Rosetta code I come across this part of
>>> LU-decomposition.
>>>
>>> def pivotize(m):
>>> """Creates the pivoting matrix for m."""
>>> n = len(m)
>>> ID = [[float(i == j) for i in xrange(n)] for j in xrange(n)]
>>> for j in xrange(n):
>>> row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
>>> if j != row:
>>> ID[j], ID[row] = ID[row], ID[j]
>>> return ID
>>>
>>> That it's using a cast from boolean to float and using
>>> at the other moment a float as a boolean, suggest that this
>>> code is a bit too clever for its own good, but anyway.
>>>
>>> My problem is with the max. I never saw a max with a key.
>>>
>>> In my python help(max) doesn't explain the key. It says that
>>> max can handle an iterator (I didn't know that), and you can
>>> pass and optional "key=func", but that's all.
>>>
>>> I expect it to be something like
>>>   elements in the iterator are taken into account only if the
>>>   key applied to the iterator evaluates to a True value.
>>>
>>> However that doesn't pan out:
>>> "
>>> max(xrange(100,200), key=lambda i: i%17==0 )
>>> 102
>>> "
>>>
>>> I expect the maximum number that is divisible by 17 in the
>>> range, not the minimum.
>>>
>>> Can anyone shed light on this?
>>
>>Given a function f() max(items, key=f) returns the element of the `items`
>>sequence with the greatest f(element), e. g. for
>>
>>max(["a", "bcd", "ef"], key=len)
>>
>>the values 1, 3, 2 are calculated and the longest string in the list is
>>returned:
>>
> max(["a", "bcd", "ef"], key=len)
>>'bcd'
>>
>>If there is more than one item with the maximum calculated the first is
>>given, so for your attempt
>>
>>max(xrange(100,200), key=lambda i: i%17==0 )
> 
>>
>>the values False, False, True, False, ... are calculated and because
>>
> True > False
>>True
>>
>>the first one with a True result is returned.
>>
> 
> So in that case max doesn't return the maximum (True), but instead
> something else.
> 
> Useful as that function may be, it shouldn't have been called max.
> 
> I don't blame myself for being misled.

I believe you still misunderstand. Again, this time with an almost real-
world car example:

max(values key=key)

calculates key(value) for every value in values. key() can be len() or an 
attribute getter, so that

max(cars, key=lambda car: car.weight) 

finds the heaviest car and

max(cars, key=lambda car: car.speed)

finds the fastest car. (If there is a tie the first car with maximum 
weight/speed is returned.)

The advantage of this approach is that you don't have to choose a "natural" 
order, i. e. should

max(cars)

find the fastest, or the heaviest, or the [you name it] car?

Also, you are really interested in the car, and

max(car.speed for car in cars)

would only give you the speed of the fastest car, not the car object itself. 
To find the fastest car without a key argument you'd have to write

fastest_car = max((car.speed, car) for car in cars)[-1]

or even

fastest_car = max((car.speed, i, car) for (i, car) in enumerate(cars))[-1]

if you are thorough and want the first car in the sequence with maximum 
speed or have to deal with car objects that aren't comparable.

The example where the key returns a boolean value is very uncommon, but 
booleans are not treated specially. So while you can write

first_red_car = max(cars, key=lambda car: car.color == RED)
if first_red_car.color == RED:
print(first_red_car)
else:
print("no red cars available")


that is unidiomatic. It is also inefficient because max() always iterates 
over the whole cars sequence in search for an even redder car. False == 0, 
and True == 1, and max() cannot be sure that the key function will never 
return 2 or TruerThanTrue ;) -- but the programmer usually knows.

Better:

red_cars = (car for car in cars if car.color == RED)
first_red_car = next(red_cars, None)
if first_red_car is not None:
print(first_red_car)
else:
print("no red cars available")


PS: Another thing to consider is the similarity with sorted().
You can sort by speed 

sorted(cars, key=lambda car: car.speed)

or "redness"

sorted(cars, key=lambda car: car.color == RED)

but you will see the former much more often than the latter.


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Jussi Piitulainen
Albert van der Horst writes:
> Chris Angelico wrote:
> > If there's no clear maximum, it can't do any better than
> > that. It's still returning something for which there is no
> > greater.
> 
> I agree that it is a useful function and that it is doing
> the right thing. What is wrong is the name.
> I refer to the fact that it is not returning the maximum.
> It returns the iterator value that leads to the maximum.
> A function that doesn't return a maximum shouldn't be called
> maximum.

It's called max. A maximal element need not be unique even in
mathematics: .
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Jussi Piitulainen
Albert van der Horst writes:

> Useful as that function [Python's max with a key] may be, it
> shouldn't have been called max.

The meaning of the key should be added to help(max), if it still isn't
- "returns a maximal element or an element that maximizes the key".

In some communities they call it arg max, with a thin space between
the components of the name. Or maybe no space: argmax.

Would you also want sorted called something else when used with a key?
Because it doesn't produce a sorted list of the keys either:

  >>> data = ("short", "long", "average")

  >>> sorted(data, key=len)
  ['long', 'short', 'average']
  >>> max(data, key=len)
  'average'

  >>> sorted(map(len, data))
  [4, 5, 7]
  >>> max(map(len, data))
  7

While the key is not a filter, a filter is as available as the map
above:

  >>> max(filter(lambda i : i % 17 == 0, range(100, 200)))
  187
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Albert van der Horst
In article ,
Chris Angelico   wrote:
>On Thu, Dec 4, 2014 at 9:09 PM, Albert van der Horst
> wrote:
>>>If there is more than one item with the maximum calculated the first is
>>>given, so for your attempt
>>>
>>>max(xrange(100,200), key=lambda i: i%17==0 )
>>
>>>
>>>the values False, False, True, False, ... are calculated and because
>>>
>> True > False
>>>True
>>>
>>>the first one with a True result is returned.
>>>
>>
>> So in that case max doesn't return the maximum (True), but instead
>> something else.
>>
>> Useful as that function may be, it shouldn't have been called max.
>>
>> I don't blame myself for being misled.
>
>If lots of them are equally the largest, by whatever definition of
>largest you have, it has to do one of three things:
>
>1) Raise an exception
>2) Return multiple items (either as a tuple, or a generator, or something)
>3) Pick one of them and return it.
>
>Python's max() does the third, and for the picking part, uses the
>first one it comes across - a decent way to do it.
>
>If there's no clear maximum, it can't do any better than that. It's
>still returning something for which there is no greater.

I agree that it is a useful function and that it is doing
the right thing. What is wrong is the name.
I refer to the fact that it is not returning the maximum.
It returns the iterator value that leads to the maximum.
A function that doesn't return a maximum shouldn't be called
maximum.

>
>ChrisA
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Chris Angelico
On Thu, Dec 4, 2014 at 9:09 PM, Albert van der Horst
 wrote:
>>If there is more than one item with the maximum calculated the first is
>>given, so for your attempt
>>
>>max(xrange(100,200), key=lambda i: i%17==0 )
>
>>
>>the values False, False, True, False, ... are calculated and because
>>
> True > False
>>True
>>
>>the first one with a True result is returned.
>>
>
> So in that case max doesn't return the maximum (True), but instead
> something else.
>
> Useful as that function may be, it shouldn't have been called max.
>
> I don't blame myself for being misled.

If lots of them are equally the largest, by whatever definition of
largest you have, it has to do one of three things:

1) Raise an exception
2) Return multiple items (either as a tuple, or a generator, or something)
3) Pick one of them and return it.

Python's max() does the third, and for the picking part, uses the
first one it comes across - a decent way to do it.

If there's no clear maximum, it can't do any better than that. It's
still returning something for which there is no greater.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-12-04 Thread Albert van der Horst
In article ,
Peter Otten  <__pete...@web.de> wrote:
>Albert van der Horst wrote:
>
>> In the Rosetta code I come across this part of
>> LU-decomposition.
>>
>> def pivotize(m):
>> """Creates the pivoting matrix for m."""
>> n = len(m)
>> ID = [[float(i == j) for i in xrange(n)] for j in xrange(n)]
>> for j in xrange(n):
>> row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
>> if j != row:
>> ID[j], ID[row] = ID[row], ID[j]
>> return ID
>>
>> That it's using a cast from boolean to float and using
>> at the other moment a float as a boolean, suggest that this
>> code is a bit too clever for its own good, but anyway.
>>
>> My problem is with the max. I never saw a max with a key.
>>
>> In my python help(max) doesn't explain the key. It says that
>> max can handle an iterator (I didn't know that), and you can
>> pass and optional "key=func", but that's all.
>>
>> I expect it to be something like
>>   elements in the iterator are taken into account only if the
>>   key applied to the iterator evaluates to a True value.
>>
>> However that doesn't pan out:
>> "
>> max(xrange(100,200), key=lambda i: i%17==0 )
>> 102
>> "
>>
>> I expect the maximum number that is divisible by 17 in the
>> range, not the minimum.
>>
>> Can anyone shed light on this?
>
>Given a function f() max(items, key=f) returns the element of the `items`
>sequence with the greatest f(element), e. g. for
>
>max(["a", "bcd", "ef"], key=len)
>
>the values 1, 3, 2 are calculated and the longest string in the list is
>returned:
>
 max(["a", "bcd", "ef"], key=len)
>'bcd'
>
>If there is more than one item with the maximum calculated the first is
>given, so for your attempt
>
>max(xrange(100,200), key=lambda i: i%17==0 )

>
>the values False, False, True, False, ... are calculated and because
>
 True > False
>True
>
>the first one with a True result is returned.
>

So in that case max doesn't return the maximum (True), but instead
something else.

Useful as that function may be, it shouldn't have been called max.

I don't blame myself for being misled.

Groetjes Albert
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How is max supposed to work, especially key.

2014-11-27 Thread Peter Otten
Albert van der Horst wrote:

> In the Rosetta code I come across this part of
> LU-decomposition.
> 
> def pivotize(m):
> """Creates the pivoting matrix for m."""
> n = len(m)
> ID = [[float(i == j) for i in xrange(n)] for j in xrange(n)]
> for j in xrange(n):
> row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
> if j != row:
> ID[j], ID[row] = ID[row], ID[j]
> return ID
> 
> That it's using a cast from boolean to float and using
> at the other moment a float as a boolean, suggest that this
> code is a bit too clever for its own good, but anyway.
> 
> My problem is with the max. I never saw a max with a key.
> 
> In my python help(max) doesn't explain the key. It says that
> max can handle an iterator (I didn't know that), and you can
> pass and optional "key=func", but that's all.
> 
> I expect it to be something like
>   elements in the iterator are taken into account only if the
>   key applied to the iterator evaluates to a True value.
> 
> However that doesn't pan out:
> "
> max(xrange(100,200), key=lambda i: i%17==0 )
> 102
> "
> 
> I expect the maximum number that is divisible by 17 in the
> range, not the minimum.
> 
> Can anyone shed light on this?

Given a function f() max(items, key=f) returns the element of the `items` 
sequence with the greatest f(element), e. g. for

max(["a", "bcd", "ef"], key=len)

the values 1, 3, 2 are calculated and the longest string in the list is 
returned:

>>> max(["a", "bcd", "ef"], key=len)
'bcd'

If there is more than one item with the maximum calculated the first is 
given, so for your attempt

max(xrange(100,200), key=lambda i: i%17==0 )

the values False, False, True, False, ... are calculated and because

>>> True > False
True

the first one with a True result is returned.

-- 
https://mail.python.org/mailman/listinfo/python-list


How is max supposed to work, especially key.

2014-11-27 Thread Albert van der Horst
In the Rosetta code I come across this part of
LU-decomposition.

def pivotize(m):
"""Creates the pivoting matrix for m."""
n = len(m)
ID = [[float(i == j) for i in xrange(n)] for j in xrange(n)]
for j in xrange(n):
row = max(xrange(j, n), key=lambda i: abs(m[i][j]))
if j != row:
ID[j], ID[row] = ID[row], ID[j]
return ID

That it's using a cast from boolean to float and using
at the other moment a float as a boolean, suggest that this
code is a bit too clever for its own good, but anyway.

My problem is with the max. I never saw a max with a key.

In my python help(max) doesn't explain the key. It says that
max can handle an iterator (I didn't know that), and you can
pass and optional "key=func", but that's all.

I expect it to be something like
  elements in the iterator are taken into account only if the
  key applied to the iterator evaluates to a True value.

However that doesn't pan out:
"
max(xrange(100,200), key=lambda i: i%17==0 )
102
"

I expect the maximum number that is divisible by 17 in the
range, not the minimum.

Can anyone shed light on this?

Groetjes Albert
-- 
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

-- 
https://mail.python.org/mailman/listinfo/python-list