在Python中通过分组从列表列表创建新列表

3
这个问题与我的另一个问题有关:使用sox和python静音基于时间戳列表的音频区域 如果q=[[0.0,4.0],[10.0,12.0],[15.0,20.0],[21.0,28.0],[32.0,36.0],[41.0,44.0]]
新列表q'应该是[[4.0,10.0],[12.0,15.0],[20.0,21.0],[28.0,32.0],[36.0,41.0]]
我所做的是:
import numpy
q= [[0.0,4.0], [10.0,12.0], [15.0,20.0], [21.0,28.0], [32.0,36.0],[41.0,44.0]]
x= []       
print "in between"
for t in range(len(q)-1):
    a,b=q[t][1],q[t+1][0]
    x.append([a,b])

for i in x:
    print i

输出:

[4.0, 10.0]
[12.0, 15.0]
[20.0, 21.0]
[28.0, 32.0]
[36.0, 41.0]  

更新:我希望将两个时间戳添加到我的^输出中。

上下文:这些时间戳是指特定片段的起始时间和结束时间。

假设这些片段不是从零开始的,而是从 3.0 开始:q= [[3.0,4.0], [10.0,12.0], [15.0,20.0], [21.0,28.0], [32.0,36.0],[41.0,44.0]] ,并且文件在 50.0 结束。

除了原始输出外,我还想添加区间:[0.0,3][44.0,50.0] ,以便我可以消除这些区域的声音。

为此,我只需执行以下操作:

import numpy
speaker_segments= [[3.0,4.0], [10.0,12.0], [15.0,20.0], [21.0,28.0], [32.0,36.0],[41.0,44.0]]
segments_to_silence = []
starting= 0.0
end= 50.0
# simple output
for t in range(len(speaker_segments)-1):
        a, b = speaker_segments[t][1],speaker_segments[t+1][0]
        segments_to_silence.append([a, b])
val = len(speaker_segments)
y= speaker_segments[val-1][1]


# appending end of segment item and end of file item to output i.e [44.0,50.0]. 
if end >y:
    a,b =y,end
    segments_to_silence.append([a,b]) 

print "appending end regions"
print segments_to_silence

# appending the starting portions  0.0 - 3.0 :
f=speaker_segments[0][0]
if starting < f:
    a=starting
    b=f
    segments_to_silence.append([a,b])
print "appending beginning regions"
print segments_to_silence

输出:

appending end regions:
[[4.0, 10.0], [12.0, 15.0], [20.0, 21.0], [28.0, 32.0], [36.0, 41.0], [44.0, 50.0]]
appending beginning regions:
[[4.0, 10.0], [12.0, 15.0], [20.0, 21.0], [28.0, 32.0], [36.0, 41.0], [44.0, 50.0], [0.0, 3.0]]   

是否可以将追加的[0.0,3.0]移动到开头?这样它们就在排序列表中并按时间顺序排列了吗?

更新2: 我只需要重新排列if条件语句,使[0.0,x.x]先出现,然后是中间部分,最后是文件结尾[50.0]。

非常感谢大家的快速响应!:)


1
更好的方式是指什么?更高效?还是更简洁的代码? - francisco sollima
抱歉没有说明清楚。如果有更高效的方法,我会将这些最终输出传递给填充和修剪函数,以消除我传递的任何内容。 - kRazzy R
3个回答

5

使用 zip列表推导式,你可以做到以下操作:

x = [[a[1], b[0]] for a, b in zip(q, q[1:])]

由于您正在使用 Python 2,最好使用迭代器版本的 zipitertools.izip

from itertools import izip

x = [[a[1], b[0]] for a, b in izip(q, q[1:])]

编辑:正如Jean-François在评论中指出的那样,使用itertools.islice

from itertools import islice, izip

x = [[a[1], b[0]] for a, b in izip(q, islice(q, 1, None))]

2
顺便提一下,使用迭代器版本的 slice 来处理 q[1:],避免创建任何临时列表。 - Jean-François Fabre

4
你可以将其压平,丢弃第一个,然后重新分组:
>>> q = [[0.0,4.0], [10.0,12.0], [15.0,20.0], [21.0,28.0], [32.0,36.0],[41.0,44.0]]
>>> from itertools import chain, islice
>>> list(map(list, zip(*2*(islice(chain(*q), 1, None),))))
[[4.0, 10.0], [12.0, 15.0], [20.0, 21.0], [28.0, 32.0], [36.0, 41.0]]

Python 2 版本:

>>> from itertools import chain, islice, izip
>>> map(list, izip(*2*(islice(chain(*q), 1, None),)))

这只是减少了行数,但没有减少代码的量,也绝对不会更易理解... - mrCarnivore

0

你也可以使用 itertools.groupby

q= [[0.0,4.0], [10.0,12.0], [15.0,20.0], [21.0,28.0], [32.0,36.0],[41.0,44.0]]
new_q = list(itertools.chain.from_iterable(q))
n = [(a, list(b)) for a, b in itertools.groupby(sorted(new_q, key=lambda x:any(a == x for a, b in q)), key=lambda x:any(a == x for a, b in q))]
final_data = [[a, b] for a, b in zip(dict(n)[0], dict(n)[1][1:])]

输出:

[[4.0, 10.0], [12.0, 15.0], [20.0, 21.0], [28.0, 32.0], [36.0, 41.0]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接