Means of comparing slices for intersection or containment containment and computing intersections or unions

I am purposefully proposing this for slices as opposed to ranges because it is about the bounds of the slices, not the items in synthetic sequences. Also, slices can refer to any type of value, not just integers. Presumably, these operations would raise exceptions when used with slices that have `step` values other than `None`. Alternatively, those could hypothetically be valid in restricted cases such as when all properties are either int or Fraction types. Probably better to have them be simply unsupported though. ``` a in b # True if <a> is fully contained within <b> a.intersects(b) # True if any value could be within both <a> and <b> a & b # Intersection of <a> and <b> or None if no intersection a | b # Union of <a> and <b> or Exception if neither contiguous nor overlapping. ``` Also, it might be nice to be able to test whether a non-slice value falls within the slice's bounds. This would be using `x in s` as a shorthand for `s.start <= x < s.end`. Again, this is different than asking whether a value is "in" a range because a rage is a sequence of discrete integers whereas a slice represents a possibly continuous range of any kind of value to which magnitude is applicable. ``` slice(1, 2) in (0, 3) # => True because 1 >= 0 and 2 <= 3 slice(0.5, 1.5) in slice(0, 2) # => True because 0.5 >= 1.5 and 0.5 < 2 1 in (0, 3) # => True because 0 <= 1 < 3 'Joe' in slice('Alice', 'Riley') # => True because 'Alice' <= 'Joe' < 'Riley' slice(1.1, 5.9).intersects(slice(2, 10.5)) # => True because either... # 1.1 <= 2 < 5.9 or # 1.1 < 10.5 < 5.5 or # 2 <= 1.1 < 10.5 or # 2 < 5.9 < 10.5 slice(5.5, 15.5) & slice(10.25, 20.25) # => slice(10.25, 15.5) slice(5.5, 15.5) | slice(10.25, 20.25) # => slice(5.5, 20.25) slice('abc', 'fff') & slice('eee', 'xyz') # => slice('fff', 'eee') ```

Steve Jorgensen wrote:
I am purposefully proposing this for slices as opposed to ranges because it is about the bounds of the slices, not the items in synthetic sequences. Also, slices can refer to any type of value, not just integers. Presumably, these operations would raise exceptions when used with slices that have step values other than None. Alternatively, those could hypothetically be valid in restricted cases such as when all properties are either int or Fraction types. Probably better to have them be simply unsupported though. a in b # True if <a> is fully contained within <b> a.intersects(b) # True if any value could be within both <a> and <b> a & b # Intersection of <a> and <b> or None if no intersection a | b # Union of <a> and <b> or Exception if neither contiguous nor overlapping.
Also, it might be nice to be able to test whether a non-slice value falls within the slice's bounds. This would be using x in s as a shorthand for s.start <= x < s.end. Again, this is different than asking whether a value is "in" a range because a rage is a sequence of discrete integers whereas a slice represents a possibly continuous range of any kind of value to which magnitude is applicable. slice(1, 2) in (0, 3) # => True because 1 >= 0 and 2 <= 3
slice(0.5, 1.5) in slice(0, 2) # => True because 0.5 >= 1.5 and 0.5 < 2
1 in (0, 3) # => True because 0 <= 1 < 3
'Joe' in slice('Alice', 'Riley') # => True because 'Alice' <= 'Joe' < 'Riley'
slice(1.1, 5.9).intersects(slice(2, 10.5)) # => True because either... # 1.1 <= 2 < 5.9 or # 1.1 < 10.5 < 5.5 or # 2 <= 1.1 < 10.5 or # 2 < 5.9 < 10.5
slice(5.5, 15.5) & slice(10.25, 20.25) # => slice(10.25, 15.5)
slice(5.5, 15.5) | slice(10.25, 20.25) # => slice(5.5, 20.25)
slice('abc', 'fff') & slice('eee', 'xyz') # => slice('fff', 'eee')
I notice I made a couple of subtle mistakes in the above. All the more reason to implement these concepts correctly as standard. :)

Which actual use cases have you had? How much better would it have been than doing it manually? It seems like most of this would be very easy to implement yourself with the exact semantics that you prefer and find most intuitive, while other people might have different expectations. Why should this be part of Python? Have you looked at libraries like https://github.com/chaimleib/intervaltree ?

On Sat, Feb 29, 2020 at 4:37 AM Alex Hall <alex.mojaki@gmail.com> wrote:
It seems like most of this would be very easy to implement yourself with the exact semantics that you prefer and find most intuitive, while other people might have different expectations.
I have to agree here. You are proposing that a slice object be treated as a general purpose interval, but that is not, in fact what they are. This is made clear by: " Presumably, these operations would raise exceptions when used with slices that have step values other than None." and also: "whereas a slice represents a possibly continuous range of any kind of value to which magnitude is applicable." well, sort of. Given the implementation and duck typing, I suppose that's true. But in fact, slices were designed for, and are (at least mostly) used to, well, slice sequences, which are always integer indexes, and hav semantics specific to that use case: In [5]: s = slice(2,-2) In [6]: s.indices(10) Out[6]: (2, 8, 1) and what if you do use non-integers? In [7]: s = slice(2.2,-2.1) In [8]: s Out[8]: slice(2.2, -2.1, None) In [9]: s.indices(10) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-9-5c4613d5ef69> in <module> ----> 1 s.indices(10) TypeError: slice indices must be integers or None or have an __index__ method In short: slices are for, well, slicing, they are no more general intervals than range objects :-) -CHB -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython

Christopher Barker wrote:
It seems like most of this would be very easy to implement yourself with the exact semantics that you prefer and find most intuitive, while other people might have different expectations. I have to agree here. You are proposing that a slice object be treated as a general purpose interval, but that is not, in fact what they are. This is made clear by: " Presumably, these operations would raise exceptions when used with slices that have step values other than None." and also: "whereas a slice represents a possibly continuous range of any kind of value to which magnitude is applicable." well, sort of. Given the implementation and duck typing, I suppose that's true. But in fact, slices were designed for, and are (at least mostly) used to, well, slice sequences, which are always integer indexes, and hav semantics specific to
On Sat, Feb 29, 2020 at 4:37 AM Alex Hall alex.mojaki@gmail.com wrote: that use case: <snip>
OK. That does make sense to me.

Steve Jorgensen wrote:
Christopher Barker wrote:
On Sat, Feb 29, 2020 at 4:37 AM Alex Hall alex.mojaki@gmail.com wrote: It seems like most of this would be very easy to implement yourself with the exact semantics that you prefer and find most intuitive, while other people might have different expectations. I have to agree here. You are proposing that a slice object be treated as a general purpose interval, but that is not, in fact what they are. This is made clear by: " Presumably, these operations would raise exceptions when used with slices that have step values other than None." and also: "whereas a slice represents a possibly continuous range of any kind of value to which magnitude is applicable." well, sort of. Given the implementation and duck typing, I suppose that's true. But in fact, slices were designed for, and are (at least mostly) used to, well, slice sequences, which are always integer indexes, and hav semantics specific to that use case: <snip>OK. That does make sense to me.
In that case, I still do think that this kind of functionality is of enough general use to have something for it in the Python standard library, though it should probably be through the introduction of a new type (possibly named something like "bounds") since neither range nor slice is really a good fit. I'm thinking it should/would be much more limited in scope than intervaltree (which does look really nice).

On Feb 29, 2020, at 10:03, Steve Jorgensen <stevej@stevej.name> wrote:
In that case, I still do think that this kind of functionality is of enough general use to have something for it in the Python standard library, though it should probably be through the introduction of a new type (possibly named something like "bounds") since neither range nor slice is really a good fit. I'm thinking it should/would be much more limited in scope than intervaltree (which does look really nice).
There are a ton of different libraries on PyPI for interval/discrete range/range values and sets and algebra and/or arithmetic on them, not to mention related things like saturating values within bounds. They all provide different functionality with different interfaces. Why do we need to pick one (or redesign and reimplement one without even looking for it) in particular?

Andrew Barnert wrote:
On Feb 29, 2020, at 10:03, Steve Jorgensen stevej@stevej.name wrote:
In that case, I still do think that this kind of functionality is of enough general use to have something for it in the Python standard library, though it should probably be through the introduction of a new type (possibly named something like "bounds") since neither range nor slice is really a good fit. I'm thinking it should/would be much more limited in scope than intervaltree (which does look really nice). There are a ton of different libraries on PyPI for interval/discrete range/range values and sets and algebra and/or arithmetic on them, not to mention related things like saturating values within bounds. They all provide different functionality with different interfaces. Why do we need to pick one (or redesign and reimplement one without even looking for it) in particular?
To me, it just feels like a missing core feature. What I'm talking about is something far simpler and less ambitious than what I would expect to see in an external addon but something that might likely be useful to any/all such things. I have decided that it makes more sense for me to publish something like what I'm looking for in a library of tools though, and then use that as the basis for a new post after I have that ready.
participants (4)
-
Alex Hall
-
Andrew Barnert
-
Christopher Barker
-
Steve Jorgensen