简体   繁体   中英

Converting a string to a list of 2-tuples

I have strings of this shape:

d="M 997.14282,452.3622 877.54125,539.83678 757.38907,453.12006 802.7325,312.0516 950.90847,311.58322 Z"

which are (x, y) coordinates of a pentagon (the first and last letters are metadata and to be ignored). What I want is a list of 2-tuples that would represent the coordinates in floating points without all the cruft:

d = [(997.14282, 452.3622), (877.54125, 539.83678), (757.38907, 453.12006), (802.7325,312.0516), (950.90847, 311.58322)]

Trimming the string was easy:

>>> d.split()[1:-2]
['997.14282,452.3622', '877.54125,539.83678', '757.38907,453.12006', '802.7325,312.0516']

but now I want to create the tuples in a succinct way. This obviously didn't work:

>>> tuple('997.14282,452.3622')
('9', '9', '7', '.', '1', '4', '2', '8', '2', ',', '4', '5', '2', '.', '3', '6', '2', '2')

Taking the original string, I could write something like this:

def coordinates(d):
    list_of_coordinates = []
    d = d.split()[1:-2]
    for elem in d:
        l = elem.split(',')
        list_of_coordinates.append((float(l[0]), float(l[1])))
    return list_of_coordinates

which works fine:

>>> coordinates("M 997.14282,452.3622 877.54125,539.83678 757.38907,453.12006 802.7325,312.0516 950.90847,311.58322 Z")
[(997.14282, 452.3622), (877.54125, 539.83678), (757.38907, 453.12006), (802.7325, 312.0516)]

However this processing is a small and trivial part of a bigger program and I'd rather keep it as short and succinct as possible. Can anyone please show me a less verbose way to convert the string to the list of 2-tuples?

You can do this in one line using list comprehension.

x = [tuple(float(j) for j in i.split(",")) for i in d.split()[1:-2]]

This goes through d.split()[1:-2]] , each pair that should be grouped together, splits them by a comma, converts each item in that to a float, and groups them together in a tuple.

Also, you might want to use d.split()[1:-1] because using -2 cuts out the last pair of coordinates.

A note, not sure if this is intended - when you do d.split()[1:-2] , you are losing the last coordinate. Assuming that is not intentional , A one liner for this would be -

def coordinates1(d):
    return [tuple(map(float,coords.split(','))) for coords in d.split()[1:-1]]

If losing the last coordinate is intentional, use [1:-2] in the above code.

While you do all right, it's could be some compressed using list comprehension or some functional stuff (i mean "map"):

    def coordinates(d):
        d = d[2:-2].split() # yeah, split here into pairs
        d = map(str.split, d, ","*len(d)) # another split, into tokens
        # here we'd multiplied string to get right size iterable
        return list(map(tuple, d)) # and last map with creating list
        # from "map object"

Of couse it can be reduced into one-line with list comprehension, but readablity would be reduced too (while right now code is read hard). And although Guido hates functional programming i'm find this more logical... After some practice. Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM