如何合并二维Python数组中的重复项

0 投票
3 回答
729 浏览
提问于 2025-04-15 16:09

我有一组数据,类似于这个:

#  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_1Ping3_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)(假设按排序顺序发出是可以的,对吧?)。

撰写回答