如何合并二维Python数组中的重复项
我有一组数据,类似于这个:
# Start_Time End_Time Call_Type Info
1 13:14:37.236 13:14:53.700 Ping1 RTT(Avr):160ms
2 13:14:58.955 13:15:29.984 Ping2 RTT(Avr):40ms
3 13:19:12.754 13:19:14.757 Ping3_1 RTT(Avr):620ms
3 13:19:12.754 Ping3_2 RTT(Avr):210ms
4 13:14:58.955 13:15:29.984 Ping4 RTT(Avr):360ms
5 13:19:12.754 13:19:14.757 Ping1 RTT(Avr):40ms
6 13:19:59.862 13:20:01.522 Ping2 RTT(Avr):163ms
...
当我处理这些数据时,我需要把 Ping3_1
和 Ping3_2
的结果合并,算出这两行的平均值,然后把它作为一行导出,最后的结果应该像这样:
# Start_Time End_Time Call_Type Info
1 13:14:37.236 13:14:53.700 Ping1 RTT(Avr):160ms
2 13:14:58.955 13:15:29.984 Ping2 RTT(Avr):40ms
3 13:19:12.754 13:19:14.757 Ping3 RTT(Avr):415ms
4 13:14:58.955 13:15:29.984 Ping4 RTT(Avr):360ms
5 13:19:12.754 13:19:14.757 Ping1 RTT(Avr):40ms
6 13:19:59.862 13:20:01.522 Ping2 RTT(Avr):163ms
...
目前,我是把第0列和第1列连接起来,形成一个唯一的键,然后找出重复的地方,再对这些并行的 ping 进行其他处理。这样做一点也不优雅。我在想有没有更好的方法来做到这一点。谢谢!
3 个回答
0
假设重复的内容是相邻的,你可以使用这样的生成器。我想你已经有一些代码可以用来计算平均的延迟时间了。
def average_pings(ping1, ping2):
pass
def merge_pings(seq):
prev_key=prev_key=None
for item in seq:
key = item.split()[:2]
if key == prev_key:
yield average_pings(prev_item, item)
else:
yield item
prev_key=key
prev_item=item
0
我不太清楚你的数据是怎么结构的,所以我假设你用的是一个字典的列表,这样可以灵活处理。
我还假设你数据集的主要标识是“开始时间”。
for i in range(len(dataset)-1):
#Detect duplicates, assuming they are sorted properly
if dataset[i]["Start"] == dataset[i+1]["Start"]:
#Merge 'em
dataset[i+1] = merge(dataset[i], dataset[i+1])
#Deleting items from the array you are iterating over is a bad idea
dataset[i] = None
dataset = [item for item in dataset if item != None] #so just delete them later
...这里的合并就是指实际执行合并操作的函数。
这个方法可能不太优雅,有点像C语言的风格,但应该比你现在用的要好。
它们没有排序吗?
dataset.sort( (lambda x,y: return cmp(x["Start"],y["Start"])) )
现在它们应该是排序好的了。
1
假设你的重复项是相邻的(就像你问题中展示的那样),那么itertools.groupby 是识别它们为重复项的最佳方法(需要一点operator.itemgetter的帮助来提取定义身份的“关键”)。假设你有一个包含对象(比如 pings)的列表,这些对象有属性,比如 .start
和 .end
:
import itertools
import operator
def merge(listofpings):
k = operator.itemgetter('start', 'end')
for i, grp in itertools.groupby(listofpings, key=k):
lst = list(grp)
if len(lst) > 2:
item = mergepings(lst)
else:
item = lst[0]
emitping(i, item)
假设你已经有了函数 mergepings
来合并多个“重复”的 pings,以及 emitping
来发出一个编号的 ping(可以是单独的或合并的)。
如果 listofpings 还没有正确排序,只需在 for
循环之前添加 listofpings.sort(key=k)
(假设按排序顺序发出是可以的,对吧?)。