基于类似的值在python中合并数组

时间:2013-01-10 21:43:41

标签: python

我想基于每个数组的每一列中的第一个元素合并python中的两个数组。

例如,

A = ([[1, 2, 3],
[4, 5, 6],
[4, 6, 7],
[5, 7, 8], 
[5, 9, 1]])

B = ([[1, .002],
[4, .005],
[5, .006]])

这样我得到一个数组

C = ([[1, 2, 3, .002],
[4, 5, 6, .005],
[4, 6, 7, .005],
[5, 7, 8, .006],
[5, 9, 1, .006]])

更清晰:

A中的第一列是1,4,4,5,5和 B的第一列是1,4,5

因此,A中的1与B中的1匹配,得到.002

我如何在python中执行此操作?任何建议都会很棒。

5 个答案:

答案 0 :(得分:1)

是否可以修改A?:

d = dict((x[0],x[1:]) for x in B)

现在d是一个字典,其中第一列是键,后续列是值。

for lst in A:
    if lst[0] in d: #Is the first value something that we can extend?
        lst.extend(d[lst[0]])

print A

要做到不合适(受到Ashwini的回答的启发):

d = dict((x[0],x[1:]) for x in B)
C = [lst + d.get(lst[0],[]) for lst in A]

然而,使用这种方法,你需要在A和B中都有列表。如果你有一些列表和一些元组,它将会失败(尽管如果你需要它可以解决它),但它会使代码稍微复杂化。

如果有这些答案,B可以有任意数量的列

作为关于风格的旁注:我会将列表写为:

A = [[1, 2, 3],
     [4, 5, 6],
     [4, 6, 7],
     [5, 7, 8], 
     [5, 9, 1]]

我放弃了括号......它们看起来太像你在tuple中放了一个列表。 Python的自动行继续使用括号(),方括号[]或大括号{}

答案 1 :(得分:0)

(这个答案假定这些只是常规列表。如果它们是NumPy数组,你有更多选择。)

看起来您希望使用B作为查找表来查找要添加到A的每一行的值。

我首先从B中的数据中创建一个字典。实际上,B已经以正确的形式传递给dict()内置:

B_dict = dict(B)

然后你只需要逐行构建C.

对于A中的每一行,row[0]是第一个元素,因此B_dict[row[0]]是您要添加到行尾的值。因此,row + [B_dict[row[0]]是您要添加到C的行。

这是一个从A和B_dict构建C的列表理解。

C = [row + [B_dict[row[0]]] for row in A]

答案 2 :(得分:0)

您可以先将B转换为dictionary,每个子列表的第一个元素作为键,第二个元素作为值。

然后简单地遍历A并追加从字典中获取的相关值。

In [114]: A = ([1, 2, 3],
[4, 5, 6],
[4, 6, 7],
[5, 7, 8], 
[6, 9, 1])

In [115]: B = ([1, .002],
[4, .005],
[5, .006])

In [116]: [x + [dic[x[0]]] if x[0] in dic else []  for x in A]
Out[116]: 
[[1, 2, 3, 0.002],
 [4, 5, 6, 0.005],
 [4, 6, 7, 0.005],
 [5, 7, 8, 0.006],
 [6, 9, 1]]

答案 3 :(得分:0)

以下是使用itertools.product()的解决方案,可以防止必须为B创建字典:

In [1]: from itertools import product

In [2]: [lst_a + lst_b[1:] for (lst_a, lst_b) in product(A, B) if lst_a[0] == lst_b[0]]
Out[2]:
[[1, 2, 3, 0.002],
 [4, 5, 6, 0.005],
 [4, 6, 7, 0.005],
 [5, 7, 8, 0.006],
 [5, 9, 1, 0.006]]

答案 4 :(得分:0)

天真,简单的方式:

for alist in A:
    for blist in B:
        if blist[0] == alist[0]:
            alist.extend(blist[1:])
            # alist.append(blist[1]) if B will only ever contain 2-tuples.
            break  # Remove this if you want to append more than one.

这里的缺点是它的O(N ^ 2)复杂度。对于大多数小型数据集,这应该没问题。如果你正在寻找更全面的东西,你可能想看看@ mgilson的答案。一些比较:

  1. 他的回复将B中的所有内容转换为dict,并对每个元素执行列表切片。如果B中有很多值,那可能会很昂贵。这使用现有列表(无论如何,您只查看第一个值)。
  2. 因为他正在使用dicts,所以他获得了O(1)个查找时间(他的回答也假定你永远不会在A中的值的末尾附加多个值)。这意味着整体而言,他的算法将达到O(N)。您需要权衡创建字典的开销是否会超过B中值的迭代。