使用分隔符python

时间:2016-07-31 22:51:03

标签: python arrays numpy

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

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]可以变化,没有切片的单个条目也可以变化。

然后我拆分了':,'分隔符,所以我可以从float转换为字符串以便在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]

我想跟踪存在“:”分隔符的原始索引以及“:”分隔符不存在的位置,以便我可以通过以下方式将原始数组重建为一系列浮点数: / p>

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)

使用冒号存在且不存在的索引列表,唯一要做的就是从列表w /冒号中删除没有冒号的索引。我在这里发现的问题是,每次变化列表都很难得到正确的索引。这可能是因为我的方法很复杂,我正在为不同的列表使用两个不同的数组。

问题是如何以一致的方式跟踪从原始数组到新数组的索引变化。我很感激有关如何使用随机用户提供的输入最好地实现这一点的任何想法。

提前致谢!

2 个答案:

答案 0 :(得分: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.])

答案 1 :(得分:1)

你说输入数组是一个字符串,所以(使用你的例子):

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根据其文档字符串,“按顺序堆栈数组(列式)。”< / p>