2つの tuple の結合(1)

先日は、dict リスト の結合だったので今度は、tupleリストの結合

a = [ ('A',1103),('B',1104),('C',1105) ]
b = [ ('A','red'),('C','yellow'),('D','blue') ]

先頭インデックス [0] をキーとして結合する。
それぞれキーのdict を用意する

a_dict = { t[0]:t for t in a }
b_dict = { t[0]:t for t in b }

以下のように set を使う方法は、順番が定まらないので tuple として使用できない

c = [ tuple(set(at + b_dict.get(at[0],(None,None)))) for at in a ]

結合で生成する tuple タプルは、+ 演算子以外に更新する方法がないので、
演算子以外の方法として、一時的に list に変換してからマージするメソッドを
用意する

# tuple をマージするメソッド
def mergeTuple(t, u):
    x = list(t)
    for i in range(len(t)-1):
        x.append(None if u[i] is None else u[i+1])
    return tuple(x)

a LEFT JOIN b ON a[0] = b[0]

# a ← b
a_left_b = [ mergeTuple(at, b_dict.get(at[0], (None,None))) for at in a ]

b LEFT JOIN a ON b[0] = a[0]

# b ← a
b_left_a = [ mergeTuple(bt, a_dict.get(bt[0], (None,None))) for bt in b ]

a LEFT JOIN b ON a[0] = b[0] WHERE b[2] NOT NULL

# a ← b where color is not null
a_left_b_C = list(filter(lambda x:x[2] is not None, [ mergeTuple(at, b_dict.get(at[0], (None,None))) for at in a ]))

b LEFT JOIN a ON b[0] = a[0] WHERE a[2] NOT NULL

# b ← a where color is not null
b_left_a_C = list(filter(lambda x:x[2] is not None, [ mergeTuple(bt, a_dict.get(bt[0], (None,None))) for bt in b ]))
print(a_dict)
print(b_dict)
print('\n-- a LEFT JOIN b ON a.name=b.name --')
print(a_left_b)
print('\n-- b LEFT JOIN a ON b.name=a.name  --')
print(b_left_a)
print('\n-- a LEFT JOIN b ON a.name=b.name WHERE color is not null --')
print(a_left_b_C)
print('\n-- b LEFT JOIN a ON b.name=a.name WHERE id not null --')
print(b_left_a_C)

print の結果

{'A': ('A', 1103), 'B': ('B', 1104), 'C': ('C', 1105)}
{'A': ('A', 'red'), 'C': ('C', 'yellow'), 'D': ('D', 'blue')}

-- a LEFT JOIN b ON a.name=b.name --
[('A', 1103, 'red'), ('B', 1104, None), ('C', 1105, 'yellow')]

-- b LEFT JOIN a ON b.name=a.name  --
[('A', 'red', 1103), ('C', 'yellow', 1105), ('D', 'blue', None)]

-- a LEFT JOIN b ON a.name=b.name WHERE color is not null --
[('A', 1103, 'red'), ('C', 1105, 'yellow')]

-- b LEFT JOIN a ON b.name=a.name WHERE id not null --
[('A', 'red', 1103), ('C', 'yellow', 1105)]