0

I know there are other ways to do this, but I am want to use match here.

In this snip, the break piece matches for all integers > 0, but I want it to match only n' I'm using the cast because it wasn't working without it. Not working with it either but...

#times is a simple list of python datetimes

n=len(times)
for i,time in enumerate(times) :
    print(f'{i} {time}')
    match int(i):
        case 0 : 
            print('continuing') 
            continue
        case int(n) : 
            print(f'breaking for {i}')
            #break
        case __ :     
            period = times[i+1] - time
            print(period)
    
Stephen Boston
  • 971
  • 1
  • 12
  • 23

2 Answers2

1

Thank you all for comments, but I'm no closer to understanding.

But after Pranav Hosangadi solution in Python 3.10 match/case with constants I managed to make this work.

from types import SimpleNamespace
count = SimpleNamespace()
count.n = len(times)-1

for i,time in enumerate(times) :
    match i:
        case 0: 
            continue
        case count.n : 
            print(f'breaking for {i}')
            break
        case __ :     
            period = times[i+1] - time
            print(period.seconds)

I think there must be a less elaborate solution but I don't see it yet.

Barmar
  • 741,623
  • 53
  • 500
  • 612
Stephen Boston
  • 971
  • 1
  • 12
  • 23
0

As @Barmar explained in the comments, you are not matching the value of n: you are setting n to the matched value (in the match context).

Try doing

case n:
    print(f'breaking for {i} {n}')

to see what's happening.

But since the behaviour you expected is true for object properties, and since integers are objects in Python, you may use n.real (which despite the name returns an integer type): so change your case to:

case n.real:

This will work.

EDIT

Full code, as requested.

Note: since the code uses times[i+1] we need to break at len(times)-1 or we will get a "list index out of range" exception.

times = [datetime(2022,10,18), datetime(2022,9,26), datetime(2022,8,12), datetime(2022,12,31)]
n = len(times) - 1
for i,time in enumerate(times) :
    print(f'{i} {time}')
    match i:
        case 0:
            print('continuing')
            continue
        case n.real:
            print(f'breaking for {i}')
            #break #not needed: it will exit anyway
        case _:
            period = times[i+1] - time
            print(period)
gimix
  • 3,431
  • 2
  • 5
  • 21
  • It didn't work for me. After Pranav Hosangadi solution in https://stackoverflow.com/questions/67181642/python-3-10-match-case-with-constants , I tried something else. I'll put it as a post – Stephen Boston Oct 24 '22 at 18:26
  • I can assure you that it works (Py 3.10.8) - I just copy/pasted your code, fixed the double underscore typo, removed the useless `int()` casts, and replaced `n` with `n.real`. Btw this solution and the one you cite are conceptually the same: they both find a way to use an object member instead of a free variable to get the desired behaviour – gimix Oct 25 '22 at 05:43
  • I didn't doubt that it worked; I couldn't get it to work (my bad, I was sure) so I went searching furthur. I didn't want to nag. As you point out my code had many weaknesses so... Anyway. Thanks very much. If you post your complete solution I'll give it the tick. – Stephen Boston Oct 25 '22 at 12:31
  • No problems. I was just trying to make clear the point, that you need a dotted notation somehow to have the structural pattern matching work as you expected it to do – gimix Oct 25 '22 at 13:31