2013-01-10 56 views
1

我想基於每個數組的每列中的第一個元素合併兩個數組。基於類似的值在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]]) 

爲了更清楚:

所述的

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

因此,A中的1與B中的1匹配並得到s .002

我該如何在python中做到這一點?任何建議都會很棒。

+0

行是按第一個元素排序的嗎?因爲在你的例子中,他們按這種方式排序。如果這是真的,那麼你可以避免使用'dict'並獲得更快的解決方案(例如,我相信'itertools.groupby'可以提供幫助)。 – Bakuriu

+1

'B'可以有2列以上嗎? – mgilson

+0

是的行按第一個元素排序。 –

回答

0

(這個回答假設這些只是常規列表。如果他們與NumPy陣列,你有更多的選擇。)

它看起來像你想用B中查找表中查找值增加以A的每一行

因爲它發生了,我會通過使字典出的數據的B.開始,B已經是恰到好處的形式傳遞給dict()內置:

B_dict = dict(B) 

然後你j ust需要逐行構建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] 
+0

他們是NumPy數組,我可以做什麼不同? –

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 

要做到這一點出位(由阿什維尼答案的啓發):

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的自動行續行發生在圓括號(),方括號[]或大括號{}

+0

也許操作不知道括號'[',']'(和大括號)提供了自動行連續,而不僅僅是括號。 – Bakuriu

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]] 
+0

我不認爲你需要'map(tuple,B))' - 我認爲只是'dic = dict(B)'會起作用... – mgilson

+0

此外,這將失敗是'A'有一個項目在「B」沒有的第一列......我不認爲你甚至可以用'dic.get()'來解決這個問題,因爲'dic'中的項目不是列表。 – mgilson

+0

@mgilson好點,我想這可以通過使用'dict.get'輕鬆解決。 –

0

下面是使用防止不必創建字典對於B itertools.product()的解決方案:

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]] 
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中的所有內容都轉換爲字典,並對每個元素執行列表切片。如果您在B中有很多值,那可能很貴。這會使用現有的列表(無論如何,您只會查看第一個值)。
  2. 因爲他使用的是字典,他會得到O(1)查找時間(他的回答也假設你永遠不會追加多個值到A的值末尾)。這意味着總體而言,他的算法將達到O(N)。您需要衡量創建字典的開銷是否會超過B中值的迭代。