【发布时间】:2020-11-01 11:54:15
【问题描述】:
考虑一个包含许多项目的列表,每个项目都包含有关相同N 属性的信息。这些属性中的每一个都可以采用一定数量的离散值(但可能是未知的)。该列表不一定是有序的。
我想将这些项目分类到一个N 维数组中,这样每个属性仅沿其自己的轴变化,即在沿该轴的任何切片内保持不变。
简化示例:
# Three properties
prop_1 = ['01','02','03','07']
prop_2 = ['foo','bar','baz']
prop_3 = ['yellow','red']
from itertools import product
# Consider this as the input
string_list = ['_'.join(s) for s in product(prop_1, prop_2, prop_3)]
# HOWEVER...
from random import shuffle
# Inputs may be unsorted
shuffle(string_list)
我现在想将string_list 组织成一个形状为(4,3,2) 的数组,这样第一个属性沿第一个轴变化,依此类推。也就是说,预期的输出是:
array([[['01_foo_yellow','01_foo_red'],
['01_bar_yellow','01_bar_red'],
['01_baz_yellow','01_baz_red']],
[['02_foo_yellow','02_foo_red'],
['02_bar_yellow','02_bar_red'],
['02_baz_yellow','02_baz_red']],
[['03_foo_yellow','03_foo_red'],
['03_bar_yellow','03_bar_red'],
['03_baz_yellow','03_baz_red']],
[['07_foo_yellow','07_foo_red'],
['07_bar_yellow','07_bar_red'],
['07_baz_yellow','07_baz_red']]])
每个属性在任何切片中沿其自己的轴保持不变,即:
A[3,...] # All strings containing '07' as property 1
A[:,1,:] # All strings containing 'bar' as property 2
A[...,0] # All strings containing 'yellow' as property 3
即使缺少项目,该方法也应该是稳健的。例如,如果我们从输入中删除 '02_bar_yellow' 和 '03_baz_red',则输出数组的形状应该保持不变,而 None 这些条目本来会被排序:
array([[['01_foo_yellow','01_foo_red'],
['01_bar_yellow','01_bar_red'],
['01_baz_yellow','01_baz_red']],
[['02_foo_yellow','02_foo_red'],
[ None, '02_bar_red'],
['02_baz_yellow','02_baz_red']],
[['03_foo_yellow','03_foo_red'],
['03_bar_yellow','03_bar_red'],
['03_baz_yellow', None. ]],
[['07_foo_yellow','07_foo_red'],
['07_bar_yellow','07_bar_red'],
['07_baz_yellow','07_baz_red']]])
问题:
虽然以上说明了总体思路,但我实际上是想让它适用于一组“属性”是其捕获组的正则表达式 match 对象。
import re
pattern = '(\d+)_(\w+)_(\w+)'
regex = re.compile(pattern)
# Consider this as the input
matches = [re.match(s) for s in string_list]
然后我想根据每个match 对象的group() 方法给出的值进行排序。
虽然它没有完全接近解决方案,但我可以使用itertools.groupby() 沿轴按切片排序项目:
# Sort by the first capturing group
groupings = itertools.groupby(matches, key=lambda m: m.groups()[0])
grouped_strings = [[m.string for m in g] for n,g in groupings]
所以grouped_strings[3] 的内容与第一个例子中给出的切片A[3,...] 相同。但是,这些条目以扁平数组的形式给出。
我突然想到我应该能够迭代地使用itertools.groupby 来实现正确的排序,但我不太明白。同时,我想知道是否有更简单或更“pythonic”的方式来实现这一点。
【问题讨论】:
-
你考虑过使用 numpy.如果它是一个 numpy 数组,它是对
reshape()的简单调用。 -
这将使事情变得非常简单,前提是输入列表可以很容易地预先正确排序(对于简单的字符串,对于其他对象则不一定如此)。另一个问题是轴的长度可能事先不知道。另外,虽然我在原始帖子中没有提到它,但我想要一种在输入列表可能缺少项目的情况下稳健的方法。
-
如果我正确理解了您的问题,请告诉我。
标签: python arrays regex sorting grouping