Re: set.add() doesn't replace equal element

2022-12-31 Thread Ian Pilcher

On 12/30/22 17:00, Paul Bryan wrote:
It seems to me like you have to ideas of what "equal" means. You want to 
update a "non-equal/equal" value in the set (because of a different time 
stamp). If you truly considered them equal, the time stamp would be 
irrelevant and updating the value in the set would be unnecessary.


I would:

a) /not/ consider two different leases with two different time stamps to 
be equal, and
b) as already mentioned, store them in another data structure like a 
dictionary.


Not knowing the specifics of the DHCP object structure, if a DHCP lease 
object has some immutable key or other durable immutable attribute, I 
would be inclined to make that the dictionary key, and store the DHCP 
object as the value.


I have come to the conclusion that you are correct.  Thanks!

--

Google  Where SkyNet meets Idiocracy


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


Re: set.add() doesn't replace equal element

2022-12-30 Thread Paul Bryan
It seems to me like you have to ideas of what "equal" means. You want 
to update a "non-equal/equal" value in the set (because of a different 
time stamp). If you truly considered them equal, the time stamp would 
be irrelevant and updating the value in the set would be unnecessary.


I would:

a) /not/ consider two different leases with two different time stamps 
to be equal, and
b) as already mentioned, store them in another data structure like a 
dictionary.


Not knowing the specifics of the DHCP object structure, if a DHCP lease 
object has some immutable key or other durable immutable attribute, I 
would be inclined to make that the dictionary key, and store the DHCP 
object as the value.



On Fri, Dec 30 2022 at 04:27:56 PM -0600, Ian Pilcher 
 wrote:

On 12/30/22 15:47, Paul Bryan wrote:
What kind of elements are being added to the set? Can you show 
reproducible sample code?


The objects in question are DHCP leases.  I consider them "equal" if
the lease address (or IPv6 prefix) is equal, even if the timestamps 
have

changed.  That code is not small, but it's easy to demonstrate the
behavior.

>>> import datetime
>>> class Foo(object):
... def __init__(self, index):
... self.index = index
... self.timestamp = datetime.datetime.now()
... def __eq__(self, other):
... return type(other) is Foo and other.index == self.index
... def __hash__(self):
... return hash(self.index)
... def __repr__(self):
... return f'Foo({self.index}) created at 
{str(self.timestamp)}'

...
>>> f1 = Foo(1)
>>> s = { f1 }
>>> s
{Foo(1) created at 2022-12-30 16:24:12.352908}
>>> f2 = Foo(1)
>>> f2
Foo(1) created at 2022-12-30 16:24:35.489208
>>> s.add(f2)
>>> s
{Foo(1) created at 2022-12-30 16:24:12.352908}

--

Google  Where SkyNet meets 
Idiocracy





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


Re: set.add() doesn't replace equal element

2022-12-30 Thread Chris Angelico
On Sat, 31 Dec 2022 at 09:29, Ian Pilcher  wrote:
>
> On 12/30/22 15:47, Paul Bryan wrote:
> > What kind of elements are being added to the set? Can you show
> > reproducible sample code?
>
> The objects in question are DHCP leases.  I consider them "equal" if
> the lease address (or IPv6 prefix) is equal, even if the timestamps have
> changed.  That code is not small, but it's easy to demonstrate the
> behavior.

Seems the more logical approach would be to use a dictionary mapping
the lease address/prefix to the timestamp? The part that contributes
to the equality check is the key, and everything else is the value.

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


Re: set.add() doesn't replace equal element

2022-12-30 Thread Ian Pilcher

On 12/30/22 15:47, Paul Bryan wrote:
What kind of elements are being added to the set? Can you show 
reproducible sample code?


The objects in question are DHCP leases.  I consider them "equal" if
the lease address (or IPv6 prefix) is equal, even if the timestamps have
changed.  That code is not small, but it's easy to demonstrate the
behavior.

>>> import datetime
>>> class Foo(object):
... def __init__(self, index):
... self.index = index
... self.timestamp = datetime.datetime.now()
... def __eq__(self, other):
... return type(other) is Foo and other.index == self.index
... def __hash__(self):
... return hash(self.index)
... def __repr__(self):
... return f'Foo({self.index}) created at {str(self.timestamp)}'
...
>>> f1 = Foo(1)
>>> s = { f1 }
>>> s
{Foo(1) created at 2022-12-30 16:24:12.352908}
>>> f2 = Foo(1)
>>> f2
Foo(1) created at 2022-12-30 16:24:35.489208
>>> s.add(f2)
>>> s
{Foo(1) created at 2022-12-30 16:24:12.352908}

--

Google  Where SkyNet meets Idiocracy


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


RE: set.add() doesn't replace equal element

2022-12-30 Thread avi.e.gross
Ian,

Do you have some examples of things you can put in a set that you consider
equal but want to store in the set INSTEAD of any current element?

What follows is some thoughts on some methods you could build yourself.
Others re possible and someone else may present you with a module that does
what you want.

In principle, if you had a function that produced a canonical version of an
argument as a sort of FIRST choice, you might still have to do some serious
work.

Assuming alpha, beta and gamma are all what you define as equal, such as if
you consider the value of a string like "32.00" to be equal to
"32.0" or even to "64/2", then you can get ALL elements of the set
and call your function on it and  compare it to the function applied to your
new proposed set addition. So f(alpha)and f(beta) and f(gamma) would by
definition return the same result, albeit that might be an integer like 32,
or a string of "32.0" or whatever you need. 

Now are you sure the set has no "duplicates" already per your algorithm?

If you are, your algorithm would need to loop on all keys and if a key
matches using f() and the newer version is not otherwise identical, remove
the old and insert the new. You can break out of the loop at that point BUT
if there is no uniqueness guarantee, you need to process all keys every
time.

A possible improvement would be to consider various mixed approaches. You
could use a dictionary where the keys are f(whatever) and the values are the
current "whatever" as one example. The "set" then would be the values of the
dictionary when you need  that view, and the dictionary as a whole when you
want to add or delete. If you needed operations like union and intersect, it
may take more work.

And, of course, you can maintain two sets. The other set would contain only
f(whatever) while the first would contain the "whatever"s.

What you are describing may have been implemented with a concept like
partitions. An example might be the partitioning of numbers modulo N so that
numbers are considered "equal" if they leave the same remainder when divided
by N. Rather than use a set directly, this could be better done by creating
an object that manages internal data structures so asking it to add a new
number results in it calculating the remainder, seeing if it is in use, and
replacing it with the latest if needed.

Avi


-Original Message-
From: Python-list  On
Behalf Of Ian Pilcher
Sent: Friday, December 30, 2022 4:41 PM
To: python-list@python.org
Subject: set.add() doesn't replace equal element

I just discovered this behavior, which is problematic for my particular use.
Is there a different set API (or operator) that can be used to add an
element to a set, and replace any equal element?

If not, am I correct that I should call set.discard() before calling
set.add() to achieve the behavior that I want?

--

Google  Where SkyNet meets Idiocracy

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

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


Re: set.add() doesn't replace equal element

2022-12-30 Thread Chris Angelico
On Sat, 31 Dec 2022 at 08:42, Ian Pilcher  wrote:
>
> I just discovered this behavior, which is problematic for my particular
> use.  Is there a different set API (or operator) that can be used to
> add an element to a set, and replace any equal element?
>
> If not, am I correct that I should call set.discard() before calling
> set.add() to achieve the behavior that I want?
>

Use a dictionary. Initially, map everything to itself. You can then
replace things with the new keys:

>>> stuff = {}
>>> stuff[1] = 1
>>> stuff[4] = 4
>>> stuff[True] = True
>>> stuff[2] = 2
>>> stuff[4.0] = 4.0
>>> stuff
{1: True, 4: 4.0, 2: 2}

To see what's in your set, look at the dictionary's values. They will
replace any equal elements, leaving the keys unchanged.

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


Re: set.add() doesn't replace equal element

2022-12-30 Thread Paul Bryan
What kind of elements are being added to the set? Can you show 
reproducible sample code?


On Fri, Dec 30 2022 at 03:41:19 PM -0600, Ian Pilcher 
 wrote:
I just discovered this behavior, which is problematic for my 
particular

use.  Is there a different set API (or operator) that can be used to
add an element to a set, and replace any equal element?

If not, am I correct that I should call set.discard() before calling
set.add() to achieve the behavior that I want?

--

Google  Where SkyNet meets 
Idiocracy


--



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


set.add() doesn't replace equal element

2022-12-30 Thread Ian Pilcher

I just discovered this behavior, which is problematic for my particular
use.  Is there a different set API (or operator) that can be used to
add an element to a set, and replace any equal element?

If not, am I correct that I should call set.discard() before calling
set.add() to achieve the behavior that I want?

--

Google  Where SkyNet meets Idiocracy

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