Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching of lists in Python

I want to do some pattern matching on lists in Python. For example, in Haskell, I can do something like the following:

fun (head : rest) = ... 

So when I pass in a list, head will be the first element, and rest will be the trailing elements.

Likewise, in Python, I can automatically unpack tuples:

(var1, var2) = func_that_returns_a_tuple() 

I want to do something similar with lists in Python. Right now, I have a function that returns a list, and a chunk of code that does the following:

ls = my_func() (head, rest) = (ls[0], ls[1:]) 

I wondered if I could somehow do that in one line in Python, instead of two.

like image 510
mipadi Avatar asked Oct 26 '08 14:10

mipadi


People also ask

Is there pattern matching in Python?

The pattern-matching syntax introduced in Python 3.10 allows for powerful new programming techniques for decision-making in apps.

What is pattern matching explain with algorithm and example?

What Does Pattern Matching Mean? Pattern matching in computer science is the checking and locating of specific sequences of data of some pattern among raw data or a sequence of tokens. Unlike pattern recognition, the match has to be exact in the case of pattern matching.

What is pattern matching syntax?

Patterns are written in JME syntax, but there are extra operators available to specify what does or doesn't match. The pattern-matching algorithm uses a variety of techniques to match different kinds of expression.

What are pattern matching operations?

SQL pattern matching enables you to use _ to match any single character and % to match an arbitrary number of characters (including zero characters). In MySQL, SQL patterns are case-insensitive by default. Some examples are shown here.


2 Answers

So far as I know there's no way to make it a one-liner in current Python without introducing another function, e.g.:

split_list = lambda lst: (lst[0], lst[1:]) head, rest = split_list(my_func()) 

However, in Python 3.0 the specialized syntax used for variadic argument signatures and argument unpacking will become available for this type of general sequence unpacking as well, so in 3.0 you'll be able to write:

head, *rest = my_func() 

See PEP 3132 for details.

like image 72
James Bennett Avatar answered Oct 03 '22 10:10

James Bennett


First of all, please note that the "pattern matching" of functional languages and the assignment to tuples you mention are not really that similar. In functional languages the patterns are used to give partial definitions of a function. So f (x : s) = e does not mean take the head and tail of the argument of f and return e using them, but it means that if the argument of f is of the form x : s (for some x and s), then f (x : s) is equal to e.

The assignment of python is more like a multiple assignment (I suspect that was its original intention). So you write, for example, x, y = y, x to swap the values in x and y without needing a temporary variable (as you would with a simple assignment statement). This has little to do with pattern matching as it is basically a shorthand for the "simultaneous" execution of x = y and y = x. Although python allows arbitrary sequences instead of comma-separated lists, I would not suggest calling this pattern matching. With pattern matching you check whether or not something matches a pattern; in the python assignment you should ensure that the sequences on both sides are the same.

To do what you seem to want you would usually (also in functional languages) use either a auxiliary function (as mentioned by others) or something similar to let or where constructs (which you can regard as using anonymous functions). For example:

(head, tail) = (x[0], x[1:]) where x = my_func() 

Or, in actual python:

(head, tail) = (lambda x: (x[0], x[1:]))(my_func()) 

Note that this is essentially the same as the solutions given by others with an auxiliary function except that this is the one-liner you wanted. It is, however, not necessarily better than a separate function.

(Sorry if my answer is a bit over the top. I just think it's important to make the distinction clear.)

like image 43
mweerden Avatar answered Oct 03 '22 11:10

mweerden