我接受用户提供的输入字符串数组,如下所示:
x=[100.0,150.0,200.0:300.0:10.0,300.0,350.0:400.0:10.0,500.0,600.0:700.0:10.0,800.0,900.0]
由于这些是用户提供的列表,因此间隔片的顺序 [例如,200.0:300.0:10.0] 可能会有所不同,没有切片的各个条目也会有所不同。
然后我在":"分隔符上拆分,这样我就可以隐蔽地从浮点数到字符串以用于numpy.r_。然后我得到以下列表:
x_arr=[100.0,150.0,200.0,300.0,10.0,300.0,350.0,400.0,10.0,500.0,600.0,700.0,10.0,800.0,900.0]
我想跟踪存在":"分隔符的原始索引以及不存在":"分隔符的位置,以便我可以通过以下方式将原始数组重建为一系列浮点数:
np.r_[100.0, 150.0, slice(200.0,300.0,10.0), 300, slice(350.0,400.0,10.0), 500.0, slice(600,700,10),800,900]
问题是如何以一致的方式跟踪索引从原始数组到新数组的变化。关于如何通过随机用户提供的输入最好地实现这一点的任何想法,我将不胜感激。
以下是我考虑接近它的一种方法:
我将原始数组拆分为","以查找缺少":"分隔符的元素:
x_no_colon=re.split((','),x)
xh=[]
for ind in x_no_colon:
inds_wo_colon=re.findall(":",ind)
xh.append(inds_wo_colon)
使用上面的示例将返回以下内容:
xh=[[],[],[":",":"],[],[":",":"],[],[":",":"],[],[]]
然后,我可以通过以下方式识别没有冒号的索引:
x_wo_colons = [item for item in range(len(xh)) if xh[item] == []]
这将返回:
x_wo_colons=[0,1,3,6,8,9]
然后我找到带有":"分隔符的索引,使用在":"上拆分数组:
colon_arr=re.split('(:)',x)
prelim_x_with_colon=[item for item in range(len(colon_arr)) if colon_arr[item] == ':']
x_w_colon=[]
for i in prelim_x_with_colon:
if i == 1 and colon_arr[1] != ':':
x_w_colon.append(i)
elif i == 1 and colon_arr[1] == ':':
x_w_colon.append(i-1)
else:
x_w_colon_append(i-1)
对于存在冒号和不存在的索引列表,唯一要做的就是从带冒号的列表中删除不带冒号的索引。我在这里发现的问题是,对于不同的列表,很难每次都获得正确的索引。这可能是因为我的方法很复杂,并且我对不同的列表使用两个不同的数组。
问题是如何以一致的方式跟踪索引从原始数组到新数组的变化。关于如何通过随机用户提供的输入最好地实现这一点的任何想法,我将不胜感激。
提前感谢!
您是否正在尝试将此输入字符串/列表转换为数字列表/数组,同时考虑到某些项目看起来像切片?
这是我对你的字符串的实验(减去[]
(。 我会留下很多试验和错误。 这也许是有启发性的。
In [957]: txt='100.0,150.0,200.0:300.0:10.0,300.0,350.0:400.0:10.0,500.0,600.0:700.0:10.0,800.0,900.0'
我假设,
是主要的分隔符,:
次要
In [958]: txt.split(',')
Out[958]:
['100.0',
'150.0',
'200.0:300.0:10.0',
'300.0',
'350.0:400.0:10.0',
'500.0',
'600.0:700.0:10.0',
'800.0',
'900.0']
定义一个函数来处理以下项之一:
In [960]: def foo(astr):
...: items=astr.split(':')
...: if len(items)==1:
...: return float(items[0])
...: else:
...: return slice(*[float(i) for i in items])
...:
In [961]: [foo(s) for s in txt.split(',')]
Out[961]:
[100.0,
150.0,
slice(200.0, 300.0, 10.0),
300.0,
slice(350.0, 400.0, 10.0),
500.0,
slice(600.0, 700.0, 10.0),
800.0,
900.0]
In [962]: np.r_[_]
Out[962]:
array([100.0, 150.0, slice(200.0, 300.0, 10.0), 300.0,
slice(350.0, 400.0, 10.0), 500.0, slice(600.0, 700.0, 10.0), 800.0,
900.0], dtype=object)
它像我预期的那样创建切片,但np.r_
不接受文字切片;它需要:
语法。 实际上,是 Python 解释器这样做,将[a:b:c]
转换为slice(a,b,c)
对象。 似乎我们最近解决了这个问题。 与其与之抗争,不如直接跳到arange
(因为无论如何np.r_
将slices
转换为arange
或linspace
(。
In [963]: def foo(astr):
...: items=astr.split(':')
...: if len(items)==1:
...: return float(items[0])
...: else:
...: return np.arange(*[float(i) for i in items])
In [964]: [foo(s) for s in txt.split(',')]
Out[964]:
[100.0,
150.0,
array([ 200., 210., 220., 230., 240., 250., 260., 270., 280., 290.]),
300.0,
array([ 350., 360., 370., 380., 390.]),
500.0,
array([ 600., 610., 620., 630., 640., 650., 660., 670., 680., 690.]),
800.0,
900.0]
In [965]: np.concatenate(_)
...
ValueError: zero-dimensional arrays cannot be concatenated
哎呀,concatenate
不喜欢单个数字;
In [966]: def foo(astr):
...: items=astr.split(':')
...: if len(items)==1:
...: return [float(items[0])]
...: else:
...: return np.arange(*[float(i) for i in items])
In [967]: [foo(s) for s in txt.split(',')]
Out[967]:
[[100.0],
[150.0],
array([ 200., 210., 220., 230., 240., 250., 260., 270., 280., 290.]),
[300.0],
array([ 350., 360., 370., 380., 390.]),
[500.0],
array([ 600., 610., 620., 630., 640., 650., 660., 670., 680., 690.]),
[800.0],
[900.0]]
In [968]: np.concatenate(_)
Out[968]:
array([ 100., 150., 200., 210., 220., 230., 240., 250., 260.,
270., 280., 290., 300., 350., 360., 370., 380., 390.,
500., 600., 610., 620., 630., 640., 650., 660., 670.,
680., 690., 800., 900.])
看起来不错。
====
===================在最近的一个答案中,我确实找到了一种将文字slice
对象传递给元组中r_
的方法。
In [969]: def foo1(astr):
...: items=astr.split(':')
...: if len(items)==1:
...: return float(items[0])
...: else:
...: return slice(*[float(i) for i in items])
...
In [971]: tuple([foo1(s) for s in txt.split(',')])
Out[971]:
(100.0,
150.0,
slice(200.0, 300.0, 10.0),
300.0,
slice(350.0, 400.0, 10.0),
500.0,
slice(600.0, 700.0, 10.0),
800.0,
900.0)
In [972]: np.r_[tuple([foo1(s) for s in txt.split(',')])]
Out[972]:
array([ 100., 150., 200., 210., 220., 230., 240., 250., 260.,
270., 280., 290., 300., 350., 360., 370., 380., 390.,
500., 600., 610., 620., 630., 640., 650., 660., 670.,
680., 690., 800., 900.])
你说输入数组是一个字符串,所以(使用你的例子(:
x = '[100.0,150.0,200.0:300.0:10.0,300.0,350.0:400.0:10.0,500.0,600.0:700.0:10.0,800.0,900.0]'
然后我们将x
按,
拆分,然后将元素拆分为:
:
x = x[1:-1].split(',')
x = ([float(y) for y in elt.split(':')] for elt in x)
我把x
变成了发电机,但现在基本上是
[[100.0], [150.0], [200.0, 300.0, 10.0], [300.0], [350.0, 400.0, 10.0], [500.0], [600.0, 700.0, 10.0], [800.0], [900.0]]
在这一点上,我不知道如何使用numpy.r_
创建您想要的数组,但我认为可以通过以下方法实现相同的目标
x = (y if len(y) == 1 else np.arange(*y) for y in x)
result = np.hstack(x)
这里np.arange
是 numpy 的range
,它接受float
参数,并根据其文档字符串np.hstack
"按顺序水平堆叠数组(按列("。