简体   繁体   中英

Double list comprehension in Python - finding borders coordinates

Given (x,y) , I want the collection:

[(0,0),(0,y),(1,0),(1,y),(2,0),(2,y)...(x-1,0),(x-1,y),(x,0),(x,y),
             (0,1),(x,1),(0,2),(x,2)...(0,y-1),(x,y-1)]

(I don't really care if it is a list, set, or any other type of collection.)

I've experimented with several permutations of list comps, nothing has really worked.

I found a BAD solution::

all_points = list(itertools.product([x for x in range(x+1)], [y for y in range(y+1)]))
border = [xy for xy in all_points if xy[0]==0 or xy[0]==x or xy[1]==0 or xy[1]==y]

But I really hate this solution and am wondering if there is a more direct approach.

EDIT

The BAD solution can be made better, as mentioned below in comments:

all_points = list(itertools.product(range(x+1), range(y+1))
border = [xy for xy in all_points if xy[0]==0 or xy[0]==x or xy[1]==0 or xy[1]==y]

But the problem remains --- i'm just getting all the coords and then dropping the ones that aren't in the comp...

EDIT

The BAD solution can be made better still...

border = [xy for xy in itertools.product(range(x+1), range(y+1)) if xy[0]==0 or xy[0]==x or xy[1]==0 or xy[1]==y]

But I don't know how I feel about this...

EDIT -- what I really want to know is...

Is there a way to do some kind of (I dunno) recursive or loopy list comprehension that returns the desired results by directly building the list?

I can solve the practical problem of finding the coords with the bad solution. But I want to grok list comps better.

If you really want a list comprehension here's one.

l = sorted({j for i in [[[(i, y), (i, 0)] for i in range(x+1)] + [[(x, i), (0, i)] for i in range(y+1)]][0] for j in i})

This will return a sorted set of tuple s.

as list comprehension perhaps like this

def border(x,y):
    return [ (a,b) for a in range(x+1) for b in range(y+1) if 0 in (a,b) or x==a or y==b ]

But I rather produce directly what I need instead of searching for some esoteric and/or potentially inefficient way of doing it, is better to be clear than clever.

Like this

def border(x,y):
    for p in range(x+1):
        yield (p,0)
        yield (p,y)
    for p in range(1,y):
        yield (0,p)
        yield (x,p)

and this one is way more efficient as it don't waste time producing unnecessary stuff just to be discarded

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