【问题标题】:Combine two array's data using inner join使用内连接合并两个数组的数据
【发布时间】:2013-07-14 23:58:05
【问题描述】:

我在数组中有两个数据集:

arr1 = [
  ['2011-10-10', 1, 1],
  ['2007-08-09', 5, 3],
  ...
]

arr2 = [
  ['2011-10-10', 3, 4],
  ['2007-09-05', 1, 1],
  ...
]

我想像这样将它们组合成一个数组:

arr3 = [
  ['2011-10-10', 1, 1, 3, 4],
  ...
]

我的意思是,只需将这些行与相同的 date 列合并即可。

编辑

谢谢大家,只是为了澄清,我不需要那些没有出现在两个数组中的行,只需删除它们。

【问题讨论】:

标签: python arrays arrayofarrays


【解决方案1】:

可能值得一提的是集合数据类型。因为他们的方法与问题的类型一致。集合运算符允许您使用全、内、外、左、右连接轻松灵活地连接集合。与字典一样,集合不保留顺序,但如果将集合重新转换为列表,则可以在结果连接上应用顺序。或者,您可以使用 ordered dictionary。

set1 = set(x[0] for x in arr1)
set2 = set(x[0] for x in arr2)
resultset = (set1 & set2)

这只会让你得到原始列表中日期的联合,为了重建 arr3 你需要在 arr1 和 arr2 中追加 [1:] 数据,日期在结果集中。这种重构不会像使用上面的字典解决方案那样简洁,但是对于类似的问题,使用集合值得考虑。

【讨论】:

    【解决方案2】:

    您可以将数组转换为字典,然后再转换回来。

    d1 = dict((x[0],x[1:]) for x in arr1)
    d2 = dict((x[0],x[1:]) for x in arr2)
    keys = set(d1).union(d2)
    n = []
    result = dict((k, d1.get(k, n) + d2.get(k, n)) for k in keys)
    

    【讨论】:

    • 你试过了吗?对我来说,这不是预期的输出:>>> result [['2011-10-10', 3, 4], ['2007-08-09', 5, 3], ['2007-09-05', 1, 1]]
    【解决方案3】:

    生成器函数方法,跳过日期不匹配的对应元素:

    import itertools
    def gen(a1, a2):
        for x,y in itertools.izip(a1, a2):
            if x[0] == y[0]:
                ret = list(x)
                ret.extend(y[1:])
                yield ret
            else:
                continue
    
    >>print list(gen(arr1, arr2))
    [['2011-10-10', 1, 1, 3, 4]]
    

    但是,如果可能的话,以不同的方式组织您的数据。

    【讨论】:

    • zip(或izip)只有在两个列表直接对应时才有意义。如果没有,您可能找不到任何匹配项。
    【解决方案4】:

    以不同的方式组织数据(您可以轻松将已有的数据转换为两个dicts):

    d1 = { '2011-10-10': [1, 1],
           '2007-08-09': [5, 3]
         }
    d2 = { '2011-10-10': [3, 4],
           '2007-09-05': [1, 1]
         }
    

    然后:

    d3 = { k : d1[k] + d2[k] for k in d1 if k in d2 }
    

    【讨论】:

    • 这将错过那些日期不在两组中的条目。
    • @Jan-Philip Gehrcke:“我的意思是,只需将这些行与相同的日期列合并即可。”
    • Jason,是的,他说他希望将这些合并,但他没有说他想错过其他数据点。他(或她)需要澄清。
    • 好吧,不管怎样,这是一个 简单 修改完整的外部联接:{ k : (d1[k] if k in d1 else []) + (d2[k] if k in d2 else []) for k in set(d1).union(d2) }。
    【解决方案5】:

    单字典方法:

    tmp = {}
    # add as many as you like into the outermost array.
    for outer in [arr1,arr2]:
        for inner in outer:
            start, rest = inner[0], inner[1:]
            # the list if key exists, else create a new list. Append to the result
            tmp[start] = tmp.get(start,[]) + rest
    
    output = []
    
    for k,v in tmp.iteritems():
       output.append([k] + v)
    

    这相当于完​​全外连接(即使一侧为空,也从两侧返回数据)。如果你想要一个内部连接,你可以把它改成这样:

    tmp = {}
    keys_with_dupes = []
    
    for outer in [arr1,arr2]:
        for inner in outer:
            start, rest = inner[0], inner[1:]
            original = tmp.get(start,[])
            tmp[start] = original + rest
            if original:
                keys_with_dupes.append(start)
    
    output = []
    
    for k in keys_with_dupes:
       v = tmp[k]
       output.append([k] + v)
    

    【讨论】:

      【解决方案6】:

      除非两者都是非常大的列表,否则我会使用字典:

      arr1 = [
        ['2011-10-10', 1, 1],
        ['2007-08-09', 5, 3]
      ]
      
      arr2 = [
        ['2011-10-10', 3, 4],
        ['2007-09-05', 1, 1]
      ]
      
      table_1 = dict((tup[0], tup[1:]) for tup in arr1)
      table_2 = dict((tup[0], tup[1:]) for tup in arr2)
      merged = {}
      for key, value in table_1.items():
          other = table_2.get(key)
          if other:
              merged[key] = value + other
      

      否则,对每个排序,然后以这种方式进行合并会更有效。但我想对于大多数用途来说这已经足够快了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-18
        • 1970-01-01
        • 1970-01-01
        • 2021-07-09
        • 2014-03-23
        • 1970-01-01
        • 2018-09-27
        • 2016-10-30
        相关资源
        最近更新 更多