Разделить строку после каждого второго появления неизвестного элемента - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть строка со списком координат, которая представляет полигоны. В этом списке каждый полигон имеет одинаковые начальные и конечные координаты. Мне нужно, чтобы каждый многоугольник был отдельной строкой (или списком).

' 17.17165756225586 -28.102264404296875 , 17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672, 17.17165756225586, 28.102264429 28.865726470947266 -28.761619567871094 , 28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 * 28.7616191 101 * 94 * 101 * 94 9 Итак, из этого простого примера мне нужно иметь два элемента:

One = ' 17.17165756225586 -28.102264404296875 , 17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672, 17.17165756225586 -28.102221202968 Два = ' 28,865726470947266 -28,761619567871094 , 28.80694007873535 -28,75750160217285,28.792499542236328 -28,706947326660156, 28,8657264709471666 * 87 В строке может быть больше полигонов, каждый из которых должен быть разделен. Я могу использовать только стандартные библиотеки Python для этого

Ответы [ 11 ]

0 голосов
/ 03 сентября 2018
c = '17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,\
    17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875,\
    28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,\
    28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'

c = [i.strip(' ') for i in c.split(',')]
i = 0
lst = []

while i!=len(c):
    out = c[i]    
    j = i+1

    while c[i]!=c[j]:
        out = out+','+c[j]
        j = j+1

    out = out+','+c[j]
    lst.append(out)
    out=''
    i = j+1
0 голосов
/ 03 сентября 2018

Вот еще один способ сделать это, этот подход применяется к любой длине строки, поскольку она будет основываться на заданном вами формате ввода.

strng = "17.17165756225586,-28.102264404296875,17.184370040893555,-28.200496673583984,17.1986083984375,-28.223613739013672,17.17165756225586,-28.102264404296875,28.865726470947266,-28.761619567871094,28.80694007873535,-28.75750160217285,28.792499542236328,-28.706947326660156,28.865726470947266,-28.761619567871094"
#convert to list of tuples
l_tuple = zip(*[iter(strng.split(','))]*2)
#get list of duplicate indexes
l_index=[]
for Tuple in l_tuple:
    x = [i for i,x in enumerate(l_tuple) if x == Tuple]
    if len(x)>1:
        l_index.append(x)
#get separate lists
New_list = []
for IND in list(set(map(tuple,l_index))):
    print(l_tuple[IND[0]:IND[1]+1])
    New_list.append(l_tuple[IND[0]:IND[1]+1])
0 голосов
/ 03 сентября 2018

Мне очень нравится решение @ newbie в его краткости. Вот немного более подробный / читабельный:

s = '17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875, 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'
vertices = [c.strip() for c in s.split(",")] # split and clean vertex data

polygons = []           
current_polygon = None

for vertex in vertices:
    if current_polygon is None:             # start a new polygon
        current_polygon = [vertex]
    elif current_polygon[0] == vertex:      # conclude the current polygon
        current_polygon.append(vertex)
        polygons.append(current_polygon)
        current_polygon = None
    else:                                   # continue the current polygon
        current_polygon.append(vertex)

for polygon in polygons:    # print polygons
    print(",".join(polygon))
0 голосов
/ 03 сентября 2018

Рекурсивный подход:

def split_polygons(s):
    if s == '':  # base case
        return []
    start, rest = s.split(',', 1)
    head, tail = map(lambda x: x.strip(', '), rest.split(start, 1))
    poly = start + ',' + head + start  # reconstruct the first polygon
    return [poly] + split_polygons(tail)

>>> p = '17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875, 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'
>>> split_polygons(p)
['17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.22361373901367217.17165756225586 -28.102264404296875', '28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.70694732666015628.865726470947266 -28.761619567871094']
0 голосов
/ 03 сентября 2018

входные данные ...

lst = [
    '17.17165756225586 -28.102264404296875',
    '17.184370040893555 -28.200496673583984',
    ...
    '17.1986083984375 -28.223613739013672',
    '17.17165756225586 -28.102264404296875',
    '28.865726470947266 -28.761619567871094',
    ...
    '28.80694007873535 -28.75750160217285',
    '28.792499542236328 -28.706947326660156',
    '28.865726470947266 -28.761619567871094',
]

lst1 = []
for cord in lst:
    if cord not in lst1:
        lst1.append(cord)
print(lst1)

выход:

[
    '17.17165756225586 -28.102264404296875',
    '17.184370040893555 -28.200496673583984',
    '17.1986083984375 -28.223613739013672',
    '28.865726470947266 -28.761619567871094',
    '28.80694007873535 -28.75750160217285',
    '28.792499542236328 -28.706947326660156',
    '28.865726470947266 -28.761619567871094',
]
0 голосов
/ 03 сентября 2018

Поскольку ваш ввод уже является строкой (и ваш ожидаемый результат также?), Вы можете попробовать это супер-ленивое решение, используя регулярное выражение (([^,]+).*\2) с обратными ссылками. Здесь [^,]+ - первая пара координат, .* остальные пары и \2 снова первая пара.

>>> s = '17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875, 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'
>>> re.findall(r"(([^,]+).*\2)", s)
[('17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875',
  '17.17165756225586 -28.102264404296875'),
 (' 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094',
  ' 28.865726470947266 -28.761619567871094')]

Или используйте finditer и получите group, чтобы получить список строк напрямую:

>>> [m.group() for m in re.finditer(r"(([^,]+).*\2)", s)]
['17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875',
 ' 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094']

После некоторой постобработки, чтобы получить фактические списки пар чисел (с _, являющимся результатом findall; для finditer опустите [0]):

>>> [[tuple(map(float, y.split())) for y in x[0].split(",")] for x in _]
[[(17.17165756225586, -28.102264404296875),
  (17.184370040893555, -28.200496673583984),
  (17.1986083984375, -28.223613739013672),
  (17.17165756225586, -28.102264404296875)],
 [(28.865726470947266, -28.761619567871094),
  (28.80694007873535, -28.75750160217285),
  (28.792499542236328, -28.706947326660156),
  (28.865726470947266, -28.761619567871094)]]

Для более длинных строк это, возможно, не самое быстрое решение, хотя я и не рассчитывал время.

0 голосов
/ 03 сентября 2018
s = '17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875, 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'

coord = s.split(',')

inpoly = False
poly = [[]]
start = None
for i in coord:
    poly[-1].append(i)
    if i == start:
        poly.append([])
        inpoly = False
    if not inpoly:
        start = i
        inpoly = True

print(poly)

Выход:

[['17.17165756225586 -28.102264404296875', '17.184370040893555 -28.200496673583984', '17.1986083984375 -28.223613739013672', '17.17165756225586 -28.102264404296875'], [' 28.865726470947266 -28.761619567871094', '28.80694007873535 -28.75750160217285', '28.792499542236328 -28.706947326660156', ' 28.865726470947266 -28.761619567871094']]
0 голосов
/ 03 сентября 2018
s='17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875, 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'

#convert the input in a list of points 
coordinates = [tuple(map(float,el.split())) for el in s.split(",")]

polygons = []

#find the polygons
while coordinates:
    ind = coordinates[1:].index(coordinates[0]) 
    polygons.append(coordinates[0:ind+2])
    coordinates = coordinates[ind+2:]

#output
[(17.17165756225586, -28.102264404296875), (17.184370040893555, -28.200496673583984), (17.1986083984375, -28.223613739013672), (17.17165756225586, -28.102264404296875)]
[(28.865726470947266, -28.761619567871094), (28.80694007873535, -28.75750160217285), (28.792499542236328, -28.706947326660156), (28.865726470947266, -28.761619567871094)]
0 голосов
/ 03 сентября 2018

Вот довольно уродливое, но работающее решение, просто добавляющее очевидный подход в код.

# Note that your string has inconsistent separators -- sometimes ',', sometimes ', '.
# I'm going to separate on `,` and not worry about it -- you need to work out
# what the correct separator is.
s = '17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875, 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094'

coordinates = s.split(',')

polygon = []
polygons = []

new = True

for coordinate in coordinates:
    polygon.append(coordinate)

    if new:
        start = coordinate
        new = False

    elif coordinate == start:
        polygons.append(polygon)
        polygon = []
        new = True

result = [",".join(polygon) for polygon in polygons]
print(result)

Out:
['17.17165756225586 -28.102264404296875,17.184370040893555 -28.200496673583984,17.1986083984375 -28.223613739013672,17.17165756225586 -28.102264404296875', ' 28.865726470947266 -28.761619567871094,28.80694007873535 -28.75750160217285,28.792499542236328 -28.706947326660156, 28.865726470947266 -28.761619567871094']
0 голосов
/ 03 сентября 2018
>>> lst = ['17.17165756225586 -28.102264404296875','17.184370040893555 -28.200496673583984',\
... '17.1986083984375 -28.223613739013672','17.17165756225586 -28.102264404296875',' 28.865726470947266 -28.761619567871094',\
... '28.80694007873535 -28.75750160217285','28.792499542236328 -28.706947326660156', '28.865726470947266 -28.761619567871094']

>>> lst1 =[]
>>> for cord in lst:
...    if cord not in lst1:
...         lst1.append(cord)
... 
>>> print(lst1)
['17.17165756225586 -28.102264404296875', '17.184370040893555 -28.200496673583984', '17.1986083984375 -28.223613739013672', ' 28.865726470947266 -28.761619567871094', '28.80694007873535 -28.75750160217285', '28.792499542236328 -28.706947326660156', '28.865726470947266 -28.761619567871094']
...