使用分隔符 python 跟踪数组中的项目



我接受用户提供的输入字符串数组,如下所示:

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转换为arangelinspace(。

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"按顺序水平堆叠数组(按列("。

最新更新