在嵌套列表中的所有子列表中查找子列表中相同的元素索引
Find index of element in sublist that is same across all the sublists in a nested list
我有一个这样的嵌套列表:
[[8.0, 16.275953626987484, 5.923962654520423],
[8.0, 3.0076746636087575, 17.05737063904884]),
([8.0, 3.0076746636087575, 17.05737063904884],
[8.0, -13.268278963378728, 11.133407984528427]),
([8.0, -13.268278963378728, 11.133407984528427],
[8.0, -16.275953626987487, -5.923962654520416]),
([8.0, -16.275953626987487, -5.923962654520416],
[8.0, -3.0076746636087694, -17.057370639048848]),
([8.0, -3.0076746636087694, -17.057370639048848],
[8.0, 13.268278963378716, -11.133407984528437]),
([8.0, 13.268278963378716, -11.133407984528437],
[8.0, 16.275953626987484, 5.923962654520423]]
在该列表中,我想删除子列表中在同一索引中具有相同值的元素,例如,在这里我想从所有子列表中删除 8,因为它在所有子列表中都相同索引 0.
如何在没有太多硬编码条件的情况下以简短的方式做到这一点?
这里要注意的一件事是子列表总是有 3 个元素,而外部嵌套列表的长度可以是任何长度。
编辑:
我将在这里解释我的用例以便更好地理解。其实这里的列表列表代表的是三维平面中的图形,所以子列表实际上是图形顶点在三维平面中的坐标。这就是为什么每个子列表只有 3 个项目。但是每个列表的子列表数量可能不同。它可以是 4(对于矩形),6(对于六边形)等等。
即使我有 3D 坐标,这些 figures/sketches 中的每一个都是在坐标平面(或平行于坐标平面一定距离的平面)上制作的,例如 xy 平面,或 yz 平面或 zx 平面。
现在由于整个图形是在平行于 3 个主平面的平面上制作的,因此每个顶点的坐标之一将完全相同,就像示例中 YZ 平面中的草图一样,每个顶点的 x 坐标都相同。
对于我的用例,我只想在此处的所有子列表中找到相同的坐标索引。
谢谢
这是一种使用列表理解和数据扁平化的方法。
首先,我们使用简单的递归确保列表的列表被展平
DATA = [
[[8.0, 16.275953626987484, 5.923962654520423]],
[[8.0, 3.0076746636087575, 17.05737063904884]],
[[8.0, 3.0076746636087575, 17.05737063904884]],
[[8.0, -13.268278963378728, 11.133407984528427]],
[[8.0, -13.268278963378728, 11.133407984528427]],
[[8.0, -16.275953626987487, -5.923962654520416]],
[[8.0, -16.275953626987487, -5.923962654520416]],
[[8.0, -3.0076746636087694, -17.057370639048848]],
[[8.0, -3.0076746636087694, -17.057370639048848]],
[[8.0, 13.268278963378716, -11.133407984528437]],
[[8.0, 13.268278963378716, -11.133407984528437]],
[[8.0, 16.275953626987484, 5.923962654520423]],
]
def is_last_layer(x: list) -> bool:
return isinstance(x, list) and len(x) == 3 and all(isinstance(_, (float, int)) for _ in x)
def get_flattened_list(data: list, res: list = None) -> list:
res = res or []
for x in data:
if is_last_layer(x):
res.append(x)
else:
res = get_flattened_list(data=x, res=res)
return res
FLAT_DATA = get_flattened_list(DATA)
print(FLAT_DATA)
# [
# [8.0, 16.275953626987484, 5.923962654520423],
# [8.0, 3.0076746636087575, 17.05737063904884],
# [8.0, 3.0076746636087575, 17.05737063904884],
# [8.0, -13.268278963378728, 11.133407984528427],
# [8.0, -13.268278963378728, 11.133407984528427],
# [8.0, -16.275953626987487, -5.923962654520416],
# [8.0, -16.275953626987487, -5.923962654520416],
# [8.0, -3.0076746636087694, -17.057370639048848],
# [8.0, -3.0076746636087694, -17.057370639048848],
# [8.0, 13.268278963378716, -11.133407984528437],
# [8.0, 13.268278963378716, -11.133407984528437],
# [8.0, 16.275953626987484, 5.923962654520423]
# ]
现在,我们可以使用列表理解来检索要删除的索引
index_to_remove = [i for i in range(3) if len({_[i] for _ in FLAT_DATA}) == 1]
print(index_to_remove)
# [0]
现在要获得与原始对象形状相同的结果,可以再次使用递归
def get_filtered_data(index_rm: list, data: list = None, res: list = None) -> list:
res = res or []
for x in data:
if is_last_layer(x):
return [_ for i, _ in enumerate(x) if i not in index_rm]
else:
res.append([get_filtered_data(index_rm=index_rm, data=x, res=res)])
return res
FILTERED_DATA = get_filtered_data(index_rm=index_to_remove, data=DATA)
print(FILTERED_DATA)
# [
# [[16.275953626987484, 5.923962654520423]],
# [[3.0076746636087575, 17.05737063904884]],
# [[3.0076746636087575, 17.05737063904884]],
# [[-13.268278963378728, 11.133407984528427]],
# [[-13.268278963378728, 11.133407984528427]],
# [[-16.275953626987487, -5.923962654520416]],
# [[-16.275953626987487, -5.923962654520416]],
# [[-3.0076746636087694, -17.057370639048848]],
# [[-3.0076746636087694, -17.057370639048848]],
# [[13.268278963378716, -11.133407984528437]],
# [[13.268278963378716, -11.133407984528437]],
# [[16.275953626987484, 5.923962654520423]]
# ]
你的问题看起来有点奇怪,但这是一个解决方案:
example = [
([8.0, 16.275953626987484, 5.923962654520423],
[8.0, 3.0076746636087575, 17.05737063904884]),
([8.0, 3.0076746636087575, 17.05737063904884],
[8.0, -13.268278963378728, 11.133407984528427]),
([8.0, -13.268278963378728, 11.133407984528427],
[8.0, -16.275953626987487, -5.923962654520416]),
([8.0, -16.275953626987487, -5.923962654520416],
[8.0, -3.0076746636087694, -17.057370639048848]),
([8.0, -3.0076746636087694, -17.057370639048848],
[8.0, 13.268278963378716, -11.133407984528437]),
([8.0, 13.268278963378716, -11.133407984528437],
[8.0, 16.275953626987484, 5.923962654520423])
]
def unchanging_mask(data):
def all_inner_iterables(xss):
if xss and isinstance(xss[0], (list, tuple)):
for xs in xss:
yield from all_inner_iterables(xs)
else:
yield xss
return list(map(lambda xs: len(set(xs)) == 1, zip(*all_inner_iterables(data))))
def select_columns(data, mask):
if data and isinstance(data[0], (list, tuple)):
return type(data)(select_columns(xs, mask) for xs in data)
else:
return type(data)(x for i, x in enumerate(data) if not mask[i])
mask = unchanging_mask(example)
result = select_columns(example, mask)
print(result)
它的工作原理是首先确定一个掩码,该掩码告诉它对于嵌套最深层次的每个元素,列是否始终具有相同的值。
然后将该掩码应用到嵌套结构最深层的所有值,保留类型。
它假设最深层次的元素都具有相同的大小。
为了回应您的更改,您说:
I just want to find the index of the coordinate that is same across all the sublists here for my use case.
在我的代码中,如果你这样做:
mask = unchanging_mask(example)
print(mask)
您会发现它提供了您正在寻找的答案。结果是:
[True, False, False]
因此,表示 x 坐标保持不变,但 y 和 z 不变。
我原来的解决方案中它后面的一行,以及它使用的函数:
result = select_columns(example, mask)
...只是将该掩码应用于原始数据,保留结构。
我有一个这样的嵌套列表:
[[8.0, 16.275953626987484, 5.923962654520423],
[8.0, 3.0076746636087575, 17.05737063904884]),
([8.0, 3.0076746636087575, 17.05737063904884],
[8.0, -13.268278963378728, 11.133407984528427]),
([8.0, -13.268278963378728, 11.133407984528427],
[8.0, -16.275953626987487, -5.923962654520416]),
([8.0, -16.275953626987487, -5.923962654520416],
[8.0, -3.0076746636087694, -17.057370639048848]),
([8.0, -3.0076746636087694, -17.057370639048848],
[8.0, 13.268278963378716, -11.133407984528437]),
([8.0, 13.268278963378716, -11.133407984528437],
[8.0, 16.275953626987484, 5.923962654520423]]
在该列表中,我想删除子列表中在同一索引中具有相同值的元素,例如,在这里我想从所有子列表中删除 8,因为它在所有子列表中都相同索引 0.
如何在没有太多硬编码条件的情况下以简短的方式做到这一点?
这里要注意的一件事是子列表总是有 3 个元素,而外部嵌套列表的长度可以是任何长度。
编辑:
我将在这里解释我的用例以便更好地理解。其实这里的列表列表代表的是三维平面中的图形,所以子列表实际上是图形顶点在三维平面中的坐标。这就是为什么每个子列表只有 3 个项目。但是每个列表的子列表数量可能不同。它可以是 4(对于矩形),6(对于六边形)等等。
即使我有 3D 坐标,这些 figures/sketches 中的每一个都是在坐标平面(或平行于坐标平面一定距离的平面)上制作的,例如 xy 平面,或 yz 平面或 zx 平面。
现在由于整个图形是在平行于 3 个主平面的平面上制作的,因此每个顶点的坐标之一将完全相同,就像示例中 YZ 平面中的草图一样,每个顶点的 x 坐标都相同。
对于我的用例,我只想在此处的所有子列表中找到相同的坐标索引。
谢谢
这是一种使用列表理解和数据扁平化的方法。
首先,我们使用简单的递归确保列表的列表被展平
DATA = [
[[8.0, 16.275953626987484, 5.923962654520423]],
[[8.0, 3.0076746636087575, 17.05737063904884]],
[[8.0, 3.0076746636087575, 17.05737063904884]],
[[8.0, -13.268278963378728, 11.133407984528427]],
[[8.0, -13.268278963378728, 11.133407984528427]],
[[8.0, -16.275953626987487, -5.923962654520416]],
[[8.0, -16.275953626987487, -5.923962654520416]],
[[8.0, -3.0076746636087694, -17.057370639048848]],
[[8.0, -3.0076746636087694, -17.057370639048848]],
[[8.0, 13.268278963378716, -11.133407984528437]],
[[8.0, 13.268278963378716, -11.133407984528437]],
[[8.0, 16.275953626987484, 5.923962654520423]],
]
def is_last_layer(x: list) -> bool:
return isinstance(x, list) and len(x) == 3 and all(isinstance(_, (float, int)) for _ in x)
def get_flattened_list(data: list, res: list = None) -> list:
res = res or []
for x in data:
if is_last_layer(x):
res.append(x)
else:
res = get_flattened_list(data=x, res=res)
return res
FLAT_DATA = get_flattened_list(DATA)
print(FLAT_DATA)
# [
# [8.0, 16.275953626987484, 5.923962654520423],
# [8.0, 3.0076746636087575, 17.05737063904884],
# [8.0, 3.0076746636087575, 17.05737063904884],
# [8.0, -13.268278963378728, 11.133407984528427],
# [8.0, -13.268278963378728, 11.133407984528427],
# [8.0, -16.275953626987487, -5.923962654520416],
# [8.0, -16.275953626987487, -5.923962654520416],
# [8.0, -3.0076746636087694, -17.057370639048848],
# [8.0, -3.0076746636087694, -17.057370639048848],
# [8.0, 13.268278963378716, -11.133407984528437],
# [8.0, 13.268278963378716, -11.133407984528437],
# [8.0, 16.275953626987484, 5.923962654520423]
# ]
现在,我们可以使用列表理解来检索要删除的索引
index_to_remove = [i for i in range(3) if len({_[i] for _ in FLAT_DATA}) == 1]
print(index_to_remove)
# [0]
现在要获得与原始对象形状相同的结果,可以再次使用递归
def get_filtered_data(index_rm: list, data: list = None, res: list = None) -> list:
res = res or []
for x in data:
if is_last_layer(x):
return [_ for i, _ in enumerate(x) if i not in index_rm]
else:
res.append([get_filtered_data(index_rm=index_rm, data=x, res=res)])
return res
FILTERED_DATA = get_filtered_data(index_rm=index_to_remove, data=DATA)
print(FILTERED_DATA)
# [
# [[16.275953626987484, 5.923962654520423]],
# [[3.0076746636087575, 17.05737063904884]],
# [[3.0076746636087575, 17.05737063904884]],
# [[-13.268278963378728, 11.133407984528427]],
# [[-13.268278963378728, 11.133407984528427]],
# [[-16.275953626987487, -5.923962654520416]],
# [[-16.275953626987487, -5.923962654520416]],
# [[-3.0076746636087694, -17.057370639048848]],
# [[-3.0076746636087694, -17.057370639048848]],
# [[13.268278963378716, -11.133407984528437]],
# [[13.268278963378716, -11.133407984528437]],
# [[16.275953626987484, 5.923962654520423]]
# ]
你的问题看起来有点奇怪,但这是一个解决方案:
example = [
([8.0, 16.275953626987484, 5.923962654520423],
[8.0, 3.0076746636087575, 17.05737063904884]),
([8.0, 3.0076746636087575, 17.05737063904884],
[8.0, -13.268278963378728, 11.133407984528427]),
([8.0, -13.268278963378728, 11.133407984528427],
[8.0, -16.275953626987487, -5.923962654520416]),
([8.0, -16.275953626987487, -5.923962654520416],
[8.0, -3.0076746636087694, -17.057370639048848]),
([8.0, -3.0076746636087694, -17.057370639048848],
[8.0, 13.268278963378716, -11.133407984528437]),
([8.0, 13.268278963378716, -11.133407984528437],
[8.0, 16.275953626987484, 5.923962654520423])
]
def unchanging_mask(data):
def all_inner_iterables(xss):
if xss and isinstance(xss[0], (list, tuple)):
for xs in xss:
yield from all_inner_iterables(xs)
else:
yield xss
return list(map(lambda xs: len(set(xs)) == 1, zip(*all_inner_iterables(data))))
def select_columns(data, mask):
if data and isinstance(data[0], (list, tuple)):
return type(data)(select_columns(xs, mask) for xs in data)
else:
return type(data)(x for i, x in enumerate(data) if not mask[i])
mask = unchanging_mask(example)
result = select_columns(example, mask)
print(result)
它的工作原理是首先确定一个掩码,该掩码告诉它对于嵌套最深层次的每个元素,列是否始终具有相同的值。
然后将该掩码应用到嵌套结构最深层的所有值,保留类型。
它假设最深层次的元素都具有相同的大小。
为了回应您的更改,您说:
I just want to find the index of the coordinate that is same across all the sublists here for my use case.
在我的代码中,如果你这样做:
mask = unchanging_mask(example)
print(mask)
您会发现它提供了您正在寻找的答案。结果是:
[True, False, False]
因此,表示 x 坐标保持不变,但 y 和 z 不变。
我原来的解决方案中它后面的一行,以及它使用的函数:
result = select_columns(example, mask)
...只是将该掩码应用于原始数据,保留结构。