Fuse stacked slices together Fuse a pair of repeated slices into a single slice: >>> fuse_slice(slice(1000, 2000), slice(10, 15)) slice(1010, 1015, None) This also works for tuples of slices >>> fuse_slice((slice(100, 200), slice(100, 200, 10)), ... (slice(10,
(a, b)
| 220 | |
| 221 | |
| 222 | def fuse_slice(a, b): |
| 223 | """Fuse stacked slices together |
| 224 | |
| 225 | Fuse a pair of repeated slices into a single slice: |
| 226 | |
| 227 | >>> fuse_slice(slice(1000, 2000), slice(10, 15)) |
| 228 | slice(1010, 1015, None) |
| 229 | |
| 230 | This also works for tuples of slices |
| 231 | |
| 232 | >>> fuse_slice((slice(100, 200), slice(100, 200, 10)), |
| 233 | ... (slice(10, 15), [5, 2])) |
| 234 | (slice(110, 115, None), [150, 120]) |
| 235 | |
| 236 | And a variety of other interesting cases |
| 237 | |
| 238 | >>> fuse_slice(slice(1000, 2000), 10) # integers |
| 239 | 1010 |
| 240 | |
| 241 | >>> fuse_slice(slice(1000, 2000, 5), slice(10, 20, 2)) |
| 242 | slice(1050, 1100, 10) |
| 243 | |
| 244 | >>> fuse_slice(slice(1000, 2000, 5), [1, 2, 3]) # lists |
| 245 | [1005, 1010, 1015] |
| 246 | |
| 247 | >>> fuse_slice(None, slice(None, None)) # doctest: +SKIP |
| 248 | None |
| 249 | """ |
| 250 | # None only works if the second side is a full slice |
| 251 | if a is None and isinstance(b, slice) and b == slice(None, None): |
| 252 | return None |
| 253 | |
| 254 | # Replace None with 0 and one in start and step |
| 255 | if isinstance(a, slice): |
| 256 | a = normalize_slice(a) |
| 257 | if isinstance(b, slice): |
| 258 | b = normalize_slice(b) |
| 259 | |
| 260 | if isinstance(a, slice) and isinstance(b, Integral): |
| 261 | if b < 0: |
| 262 | raise NotImplementedError() |
| 263 | return a.start + b * a.step |
| 264 | |
| 265 | if isinstance(a, slice) and isinstance(b, slice): |
| 266 | start = a.start + a.step * b.start |
| 267 | if b.stop is not None: |
| 268 | stop = a.start + a.step * b.stop |
| 269 | else: |
| 270 | stop = None |
| 271 | if a.stop is not None: |
| 272 | if stop is not None: |
| 273 | stop = min(a.stop, stop) |
| 274 | else: |
| 275 | stop = a.stop |
| 276 | step = a.step * b.step |
| 277 | if step == 1: |
| 278 | step = None |
| 279 | return slice(start, stop, step) |
searching dependent graphs…