複数のタプルデータを比較して、組み合わせる方法


例として以下のようなタプルデータがあるとします。

[code]

    data1 = (1,2), (2,1), (3,3), (4,4), (5,8), (6,7), (7,6), (8,5), (9,5), (10,7)
    data2 = (1,5), (2,5), (3,1), (4,2), (5,4), (6,3), (7,3), (8,3)
    data3 = (1,3), (2,2), (3,1), (4,3), (5,3)
    
[/code]

`data`はそれぞれ10から8、8から5、5から3への全射のように表現されています。(カッコ内の左の数字から右の数字への写像と考えてください)  
この`data`から最終的に、10から3への写像を作りたいのです。  
どのようなルールでそれを行うかというと、まず、`data1`の1~10の数字の写像先である1~8の数字と、`data2`の写像元である1~8の数字を比較します。数字が一致したところに写像をつなげていきます。これを`data3`の写像先である1~3の数字にまとめたいのです。  
上記のデータから例を出しますと、`data1`の`(1,2)`を見ると、写像先である`2`は`data2`の写像元である`(2,5)`に一致します。さらに写像先である`5`は`data3`の`(5,3)`に一致します。なので求める解は`data1`の写像元である`1`と,  
`data3`の写像先である`3`を組み合わせた`(1,3)`となります。

このロジックを基に、出力として10組のタプル表現が欲しいです。どなたかこれをプログラムで表現できる方は、是非ご回答のほどよろしくお願いします。

[edit]:

[code]

    data1 = [(1,2), (2,1), (3,3), (4,4), (5,8), (6,7), (7,6), (8,5), (9,5), (10,7)]
    data2 = [(1,5), (2,5), (3,1), (4,2), (5,4), (6,3), (7,3), (8,3)]
    data3 = [(1,3), (2,2), (3,1), (4,3), (5,3)]
    
    x1 = []
    z = []
    for i in range(0, len(data1)):
        x1.append(data1[i][1])
    
    for i in x1:
        for j in range(0, len(data2)):
            if i == data2[j][0]:
                z.append((data1[i][0], data2[j][1]))
    
    print(z)
    
[/code]




以下は more_itertools の [map_reduce](https://more-
itertools.readthedocs.io/en/stable/api.html#more_itertools.map_reduce) と
[first_true](https://more-
itertools.readthedocs.io/en/stable/api.html#more_itertools.first_true)
を使う方法です。

[code]

    from more_itertools import map_reduce, first_true
    
    data1 = [(1, 2), (2, 1), (3, 3), (4, 4), (5, 8), (6, 7), (7, 6), (8, 5), (9, 5), (10, 7)]
    data2 = [(1, 5), (2, 5), (3, 1), (4, 2), (5, 4), (6, 3), (7, 3), (8, 3)]
    data3 = [(1, 3), (2, 2), (3, 1), (4, 3), (5, 3)]
    
    result = map_reduce(
      data1,
      lambda x: x[0],
      lambda x:
        first_true(data2, pred=lambda y: y[0] == x[1]),
      lambda x:
        first_true(data3, pred=lambda y: y[0] == x[0][1])
    )
    
    result = [(k, v[1]) for k, v in result.items()]
    print(result)
    [(1, 3), (2, 3), (3, 3), (4, 2), (5, 1), (6, 1), (7, 1), (8, 3), (9, 3), (10, 1)]
    
[/code]




以下は more_itertools の [map_reduce](https://more-
itertools.readthedocs.io/en/stable/api.html#more_itertools.map_reduce) と
[first_true](https://more-
itertools.readthedocs.io/en/stable/api.html#more_itertools.first_true)
を使う方法です。

[code]

    from more_itertools import map_reduce, first_true
    
    data1 = [(1, 2), (2, 1), (3, 3), (4, 4), (5, 8), (6, 7), (7, 6), (8, 5), (9, 5), (10, 7)]
    data2 = [(1, 5), (2, 5), (3, 1), (4, 2), (5, 4), (6, 3), (7, 3), (8, 3)]
    data3 = [(1, 3), (2, 2), (3, 1), (4, 3), (5, 3)]
    
    result = map_reduce(
      data1,
      lambda x: x[0],
      lambda x:
        first_true(data2, pred=lambda y: y[0] == x[1]),
      lambda x:
        first_true(data3, pred=lambda y: y[0] == x[0][1])
    )
    
    result = [(k, v[1]) for k, v in result.items()]
    print(result)
    [(1, 3), (2, 3), (3, 3), (4, 2), (5, 1), (6, 1), (7, 1), (8, 3), (9, 3), (10, 1)]
    
[/code]

