在许多列表的列表中查找子列表的数量
Find number of sublists in list of many lists
我在编码的项目中遇到了一些问题,非常感谢您的帮助...我认为这也是一个有趣的问题:-)
我正在尝试格式化来自 geojson 的坐标,如下所示(由于它们很长,我将其缩短并粘贴到此处)。
[[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
我需要它们最终看起来像这样:
“54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062,”
目前我已经使用下面的代码工作,其中变量 poly 首先被分配给一个坐标块,就像上面发布的第一个一样。
def threetimes(func):
"""Executes the function on its own output two times."""
@functools.wraps(func)
def wrapper_three_times(*args, **kwargs):
value = func(*args, **kwargs)
value2 = func(value)
value3 = func(value2)
return value3
return wrapper_three_times
def swap_pairs(poly):
"""
Turns a list like this [1, 2, 3, 4] into [2, 1, 4, 3]
:param polys: list
:return: list
"""
for i in range(0, len(poly) - 1, 2):
poly[i], poly[i + 1] = poly[i + 1], poly[i]
return poly
@threetimes
def flatten_polys(poly):
"""
Turns geojson polygons into flat lists.
:param poly: List of three lists; standard geojson polygon or multipolygon format.
:return: flat list of the polygon co-ordinates.
"""
flat_poly = [item for sublist in poly for item in sublist]
return flat_poly
poly = flatten_polys(poly)
poly = swap_pairs(poly)
polys_formatted = [str(x) + ',' + str(y) + ':' for x, y in zip(poly[0::2], poly[1::2])]
polys_formatted[-1] = polys_formatted[-1].replace(':', '')
poly_as_string = ''.join(x for x in polys_formatted)
然而,问题是有时坐标具有不同数量的子列表,而不是此处示例中的三个,即它们看起来像这样(为简洁起见再次被截断):
[[[-0.109373710729991, 51.42315755917108], [-0.105987341539958, 51.422576811743276], [-0.096906133161734, 51.422667109533435], [-0.094346733695295, 51.422818864663064], [-0.092734433338077, 51.42253994327862], [-0.088190383828824, 51.419927269261336], [-0.086425687184976, 51.419305849976176], [-0.082346001337163, 51.419771533877956], [-0.078548643992427, 51.41984782473602], [-0.080993694631571, 51.417101046706534], [-0.080475514860821, 51.415566497757084]]]
所以我想我需要的是一个函数来展平嵌套的子列表,它会重复 n 次,直到它不能再没有错误地执行...
如有任何帮助,我将不胜感激...
你可以试试这个:
coordinate_list = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
编辑:调整coord_pairs函数以捕获所有子列表。
# def flatten(iterable):
# """Recursive flattening of sublists."""
# if len(iterable) > 1:
# res = flatten(iterable[0])
# else:
# res = iterable[0]
# return res
# def coord_pairs(lists):
# out = ""
# for item in lists:
# res = flatten(item)
# out += ":".join([f"{c[1]},{c[0]}" for c in res])
# return out
def flatten(iterable):
"""Recursive flattening of sublists."""
if len(iterable) > 1:
return flatten(iterable[0])
else:
return iterable[0]
return res
def coord_pairs(lists):
out = ""
if len(lists) > 1:
for item in lists:
res = flatten(item)
out += ":".join([f"{c[1]},{c[0]}" for c in res])
else:
res = flatten(lists)
out += ":".join([f"{c[1]},{c[0]}" for c in res])
return out
# Call function to test output.
coord_pairs(coordinate_list)
输出:
'54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.24195652631595854.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676'
以下是使用递归函数的方法:
lst = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
cor = []
def func(lst):
for a in lst:
if isinstance(a,list):
if not any(isinstance(i, list) for i in a):
cor.append(f"{a[1]},{a[0]}")
func(a)
func(lst)
print(':'.join(cor))
输出:
54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676
lst_input = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 53.72242038994674], [-1.24192061729046, 52.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
# look inside the current list, if the next element is also a list flatten the current list
while type(next(iter(lst_input))).__name__ == "list":
lst_input = [item for sublist in lst_input for item in sublist]
# combine the elements of the fully flattened list as string, keep order
string_output = ":".join([", ".join([str(lst_input[j]),str(lst_input[j-1])]) for j in range(1,len(lst_input))])
试试这个,它应该一直到最后一个列表:
origx = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
print(origx)
def flat(x):
if type(x[0][0]) is list:
x=[ i for xl in x for i in xl ]
return flat(x)
else:
return x
def reformat(x):
s = ""
for pair in x:
s=s+str(pair[1])+","+str(pair[0])+":"
return s[:-1]
print(reformat(flat(origx)))
输出
54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676
您可以根据每个元素是否为列表递归展平 lst
>>> from itertools import chain
>>> lst_input = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
>>>
>>>
>>> flatten = lambda lst: [i for e in lst for i in (chain(reversed(flatten(e)), [':']) if isinstance(e, list) else [e])]
>>> lst = flatten(lst_input)
>>> lst
[':', 54.722452909315834, -1.241956526315958, ':', 54.72242038994674, -1.242505189342398, ':', 54.722713302903806, -1.24192061729046, ':', 54.722452909315834, -1.241956526315958, ':', ':', ':', 54.7271584144655, -1.270237428346303, ':', 54.72608036652354, -1.268210325997062, ':', 54.726854573664205, -1.267390512992676, ':', ':']
>>>
>>> ','.join(map(str, lst)).strip(':,').replace(',:,', ':')
'54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:::54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676'
好的,除了来自@Prem Anand 的答案外,还有另一个答案也适用于此!
这不是我的代码,它来自 realpython.com 用户的回答 -
def flatten(bad):
good = []
while bad:
e = bad.pop()
if isinstance(e, list):
bad.extend(e)
else:
good.append(e)
return good[::-1]
poly = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
poly = flatten(poly)
polys_formatted = [str(x) + ',' + str(y) + ':' for x, y in zip(poly[1::2], poly[0::2])]
poly_as_string = ''.join(x for x in polys_formatted)[:-1]
print(poly_as_string)
我在尝试输入的所有不同坐标上得到的输出是完美的。
只是为了对比,这里有一个根本不尝试遍历数据结构的方法。它会立即将其转换为字符串,然后尝试“清理”字符串以按照您的意愿显示:
POST_TRANSLATIONS = str.maketrans({'[': None, ']': None})
def flatten_polys(polygons):
array = []
for coordinates in str(polygons).split('], ['):
array.append(','.join(reversed(coordinates.split(', '))))
return ':'.join(array).translate(POST_TRANSLATIONS)
if __name__ == "__main__":
# Run some tests
poly_1 = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
print(flatten_polys(poly_1))
print()
poly_2 = [[[-0.109373710729991, 51.42315755917108], [-0.105987341539958, 51.422576811743276], [-0.096906133161734, 51.422667109533435], [-0.094346733695295, 51.422818864663064], [-0.092734433338077, 51.42253994327862], [-0.088190383828824, 51.419927269261336], [-0.086425687184976, 51.419305849976176], [-0.082346001337163, 51.419771533877956], [-0.078548643992427, 51.41984782473602], [-0.080993694631571, 51.417101046706534], [-0.080475514860821, 51.415566497757084]]]
print(flatten_polys(poly_2))
print()
poly_3 = [[[0.35734960034587, 51.691419401103474], [0.360525134769747, 51.69037987969592], [0.362860024738573, 51.69170434483416]]]
print(flatten_polys(poly_3))
输出
> python3 test.py
54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676
51.42315755917108,-0.109373710729991:51.422576811743276,-0.105987341539958:51.422667109533435,-0.096906133161734:51.422818864663064,-0.094346733695295:51.42253994327862,-0.092734433338077:51.419927269261336,-0.088190383828824:51.419305849976176,-0.086425687184976:51.419771533877956,-0.082346001337163:51.41984782473602,-0.078548643992427:51.417101046706534,-0.080993694631571:51.415566497757084,-0.080475514860821
51.691419401103474,0.35734960034587:51.69037987969592,0.360525134769747:51.69170434483416,0.362860024738573
>
我在编码的项目中遇到了一些问题,非常感谢您的帮助...我认为这也是一个有趣的问题:-)
我正在尝试格式化来自 geojson 的坐标,如下所示(由于它们很长,我将其缩短并粘贴到此处)。
[[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
我需要它们最终看起来像这样:
“54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062,”
目前我已经使用下面的代码工作,其中变量 poly 首先被分配给一个坐标块,就像上面发布的第一个一样。
def threetimes(func):
"""Executes the function on its own output two times."""
@functools.wraps(func)
def wrapper_three_times(*args, **kwargs):
value = func(*args, **kwargs)
value2 = func(value)
value3 = func(value2)
return value3
return wrapper_three_times
def swap_pairs(poly):
"""
Turns a list like this [1, 2, 3, 4] into [2, 1, 4, 3]
:param polys: list
:return: list
"""
for i in range(0, len(poly) - 1, 2):
poly[i], poly[i + 1] = poly[i + 1], poly[i]
return poly
@threetimes
def flatten_polys(poly):
"""
Turns geojson polygons into flat lists.
:param poly: List of three lists; standard geojson polygon or multipolygon format.
:return: flat list of the polygon co-ordinates.
"""
flat_poly = [item for sublist in poly for item in sublist]
return flat_poly
poly = flatten_polys(poly)
poly = swap_pairs(poly)
polys_formatted = [str(x) + ',' + str(y) + ':' for x, y in zip(poly[0::2], poly[1::2])]
polys_formatted[-1] = polys_formatted[-1].replace(':', '')
poly_as_string = ''.join(x for x in polys_formatted)
然而,问题是有时坐标具有不同数量的子列表,而不是此处示例中的三个,即它们看起来像这样(为简洁起见再次被截断):
[[[-0.109373710729991, 51.42315755917108], [-0.105987341539958, 51.422576811743276], [-0.096906133161734, 51.422667109533435], [-0.094346733695295, 51.422818864663064], [-0.092734433338077, 51.42253994327862], [-0.088190383828824, 51.419927269261336], [-0.086425687184976, 51.419305849976176], [-0.082346001337163, 51.419771533877956], [-0.078548643992427, 51.41984782473602], [-0.080993694631571, 51.417101046706534], [-0.080475514860821, 51.415566497757084]]]
所以我想我需要的是一个函数来展平嵌套的子列表,它会重复 n 次,直到它不能再没有错误地执行...
如有任何帮助,我将不胜感激...
你可以试试这个:
coordinate_list = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
编辑:调整coord_pairs函数以捕获所有子列表。
# def flatten(iterable):
# """Recursive flattening of sublists."""
# if len(iterable) > 1:
# res = flatten(iterable[0])
# else:
# res = iterable[0]
# return res
# def coord_pairs(lists):
# out = ""
# for item in lists:
# res = flatten(item)
# out += ":".join([f"{c[1]},{c[0]}" for c in res])
# return out
def flatten(iterable):
"""Recursive flattening of sublists."""
if len(iterable) > 1:
return flatten(iterable[0])
else:
return iterable[0]
return res
def coord_pairs(lists):
out = ""
if len(lists) > 1:
for item in lists:
res = flatten(item)
out += ":".join([f"{c[1]},{c[0]}" for c in res])
else:
res = flatten(lists)
out += ":".join([f"{c[1]},{c[0]}" for c in res])
return out
# Call function to test output.
coord_pairs(coordinate_list)
输出:
'54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.24195652631595854.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676'
以下是使用递归函数的方法:
lst = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
cor = []
def func(lst):
for a in lst:
if isinstance(a,list):
if not any(isinstance(i, list) for i in a):
cor.append(f"{a[1]},{a[0]}")
func(a)
func(lst)
print(':'.join(cor))
输出:
54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676
lst_input = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 53.72242038994674], [-1.24192061729046, 52.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
# look inside the current list, if the next element is also a list flatten the current list
while type(next(iter(lst_input))).__name__ == "list":
lst_input = [item for sublist in lst_input for item in sublist]
# combine the elements of the fully flattened list as string, keep order
string_output = ":".join([", ".join([str(lst_input[j]),str(lst_input[j-1])]) for j in range(1,len(lst_input))])
试试这个,它应该一直到最后一个列表:
origx = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
print(origx)
def flat(x):
if type(x[0][0]) is list:
x=[ i for xl in x for i in xl ]
return flat(x)
else:
return x
def reformat(x):
s = ""
for pair in x:
s=s+str(pair[1])+","+str(pair[0])+":"
return s[:-1]
print(reformat(flat(origx)))
输出
54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676
您可以根据每个元素是否为列表递归展平 lst
>>> from itertools import chain
>>> lst_input = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
>>>
>>>
>>> flatten = lambda lst: [i for e in lst for i in (chain(reversed(flatten(e)), [':']) if isinstance(e, list) else [e])]
>>> lst = flatten(lst_input)
>>> lst
[':', 54.722452909315834, -1.241956526315958, ':', 54.72242038994674, -1.242505189342398, ':', 54.722713302903806, -1.24192061729046, ':', 54.722452909315834, -1.241956526315958, ':', ':', ':', 54.7271584144655, -1.270237428346303, ':', 54.72608036652354, -1.268210325997062, ':', 54.726854573664205, -1.267390512992676, ':', ':']
>>>
>>> ','.join(map(str, lst)).strip(':,').replace(',:,', ':')
'54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:::54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676'
好的,除了来自@Prem Anand 的答案外,还有另一个答案也适用于此!
这不是我的代码,它来自 realpython.com 用户的回答 -
def flatten(bad):
good = []
while bad:
e = bad.pop()
if isinstance(e, list):
bad.extend(e)
else:
good.append(e)
return good[::-1]
poly = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
poly = flatten(poly)
polys_formatted = [str(x) + ',' + str(y) + ':' for x, y in zip(poly[1::2], poly[0::2])]
poly_as_string = ''.join(x for x in polys_formatted)[:-1]
print(poly_as_string)
我在尝试输入的所有不同坐标上得到的输出是完美的。
只是为了对比,这里有一个根本不尝试遍历数据结构的方法。它会立即将其转换为字符串,然后尝试“清理”字符串以按照您的意愿显示:
POST_TRANSLATIONS = str.maketrans({'[': None, ']': None})
def flatten_polys(polygons):
array = []
for coordinates in str(polygons).split('], ['):
array.append(','.join(reversed(coordinates.split(', '))))
return ':'.join(array).translate(POST_TRANSLATIONS)
if __name__ == "__main__":
# Run some tests
poly_1 = [[[[-1.241956526315958, 54.722452909315834], [-1.242505189342398, 54.72242038994674], [-1.24192061729046, 54.722713302903806], [-1.241956526315958, 54.722452909315834]]], [[[-1.270237428346303, 54.7271584144655], [-1.268210325997062, 54.72608036652354], [-1.267390512992676, 54.726854573664205]]]]
print(flatten_polys(poly_1))
print()
poly_2 = [[[-0.109373710729991, 51.42315755917108], [-0.105987341539958, 51.422576811743276], [-0.096906133161734, 51.422667109533435], [-0.094346733695295, 51.422818864663064], [-0.092734433338077, 51.42253994327862], [-0.088190383828824, 51.419927269261336], [-0.086425687184976, 51.419305849976176], [-0.082346001337163, 51.419771533877956], [-0.078548643992427, 51.41984782473602], [-0.080993694631571, 51.417101046706534], [-0.080475514860821, 51.415566497757084]]]
print(flatten_polys(poly_2))
print()
poly_3 = [[[0.35734960034587, 51.691419401103474], [0.360525134769747, 51.69037987969592], [0.362860024738573, 51.69170434483416]]]
print(flatten_polys(poly_3))
输出
> python3 test.py
54.722452909315834,-1.241956526315958:54.72242038994674,-1.242505189342398:54.722713302903806,-1.24192061729046:54.722452909315834,-1.241956526315958:54.7271584144655,-1.270237428346303:54.72608036652354,-1.268210325997062:54.726854573664205,-1.267390512992676
51.42315755917108,-0.109373710729991:51.422576811743276,-0.105987341539958:51.422667109533435,-0.096906133161734:51.422818864663064,-0.094346733695295:51.42253994327862,-0.092734433338077:51.419927269261336,-0.088190383828824:51.419305849976176,-0.086425687184976:51.419771533877956,-0.082346001337163:51.41984782473602,-0.078548643992427:51.417101046706534,-0.080993694631571:51.415566497757084,-0.080475514860821
51.691419401103474,0.35734960034587:51.69037987969592,0.360525134769747:51.69170434483416,0.362860024738573
>