【问题标题】:How to merge duplicates in 2D python arrays如何合并二维python数组中的重复项
【发布时间】:2010-12-18 01:53:10
【问题描述】:

我有一组类似这样的数据:

#  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 进行其余的特殊处理。它一点也不优雅。只是想知道什么是更好的方法。谢谢!

【问题讨论】:

  • 重复的总是在相邻的行上吗?

标签: python arrays merge duplicates


【解决方案1】:

假设您的重复项是相邻的(如您的问题所示),itertools.groupby 是将它们标识为重复项的理想方法(在operator.itemgetter 的帮助下提取定义身份的“关键”。假设你有一个对象列表(ping),其属性包括.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 来合并 > 1 个“重复” ping 的列表,以及 emitping 发出编号的 ping(裸或合并)。

如果 listofpings 尚未正确排序,只需在 for 循环之前添加 listofpings.sort(key=k)(大概按排序顺序发出就可以了,对吧?)。

【讨论】:

    【解决方案2】:

    我不确定您的数据是如何构成的,因此我将假设一个用于鸭子输入目的的 dicts 列表。

    我还假设您的数据集的真正主键是 Start。

    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
    

    ...merge 将是实际进行合并的函数。

    不优雅,C-ish,但可能比你目前使用的更好。

    它们没有排序?

    dataset.sort( (lambda x,y: return cmp(x["Start"],y["Start"])) )
    

    现在应该是了。

    【讨论】:

    • 永远不要使用 cmp 进行排序。它更慢。使用密钥:dataset.sort(key=operator.itemgetter('Start'))
    • 好吧,我想我无论如何都不会选择 Py3k。
    【解决方案3】:

    假设重复项是相邻的,您可以使用这样的生成器。我猜你已经有一些代码来平均 pings

    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
    

    【讨论】:

      猜你喜欢
      • 2017-04-12
      • 2018-02-09
      • 1970-01-01
      • 2017-05-07
      • 2018-10-04
      • 2019-02-25
      • 1970-01-01
      • 2022-07-14
      • 1970-01-01
      相关资源
      最近更新 更多