72360


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

[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]


CC BY-SA 4.0
2020-12-03T01:23:33.920
72356
2020-12-04T02:13:21.783
2020-12-03T03:42:40.317
36856
36856
question
python python3
複数のタプルデータを比較して、組み合わせる方法


以下は 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]


CC BY-SA 4.0
2020-12-03T03:41:35.237
72360
2020-12-03T03:41:35.237
72356
answer


元のコードはこの部分がおかしいです。

[code]

    x1 = []
    z = []
    for i in range(0, len(data1)):
        x1.append(data1[i][1])
    
    for i in x1:  # ここで i は写像元の値
        for j in range(0, len(data2)):
            if i == data2[j][0]:
                z.append((data1[i][0], data2[j][1]))
                              # ^ 写像元の値を添え字に使うのはおかしい
    
[/code]

このように修正すればよいと思います。

[code]

    x1 = []
    z = []
    for i in range(0, len(data1)):
        x1.append(data1[i][1])
    
    for i in range(0, len(x1)):
        for j in range(0, len(data2)):
            if x1[i] == data2[j][0]:
                z.append((data1[i][0], data2[j][1]))
    
    print(z)
    
[/code]

もっとも、わざわざ `x1` に入れる必要はないんじゃないかとか思ったり

[code]

    z = []
    for i in range(0, len(data1)):
        for j in range(0, len(data2)):
            if data1[i][1] == data2[j][0]:
                z.append((data1[i][0], data2[j][1]))
    
    print(z)
    
[/code]

(編集)  
ここまでくると添え字はいりませんね

[code]

    z = []
    for item1 in data1:
        for item2 in data2:
            if item1[1] == item2[0]:
                z.append((item1[0], item2[1]))
    
    print(z)
    
[/code]

同じように `z` と `data3` の合成を書けば `data1`~`data3`の合成が得られます。


CC BY-SA 4.0
2020-12-03T09:42:02.783
72365
2020-12-03T09:49:42.290
2020-12-03T09:49:42.290
20885
20885
72356
answer


内包表記で書いた方がわかりやすそうです。

[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)]
    
    ans = [(d1[0], d3[1]) for d1 in data1 for d2 in data2
           for d3 in data3 if d1[1] == d2[0] and d2[1] == d3[0]]
    print(ans)  # [(1, 3), (2, 3), (3, 3), (4, 2), (5, 1), (6, 1), (7, 1), (8, 3), (9, 3), (10, 1)]
    
[/code]


CC BY-SA 4.0
2020-12-03T15:25:32.883
72378
2020-12-03T15:25:32.883
41756
72356
answer


辞書で

[code]

    In [1]: 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)]
    
    In [2]: d2 = {k: v for k, v in data2}
       ...: d3 = {k: v for k, v in data3}
       ...: [(k, d3[d2[v]]) for k, v in data1]
    Out[2]:
    [(1, 3),
     (2, 3),
     (3, 3),
     (4, 2),
     (5, 1),
     (6, 1),
     (7, 1),
     (8, 3),
     (9, 3),
     (10, 1)]
    
[/code]


CC BY-SA 4.0
2020-12-04T02:13:21.783
72386
2020-12-04T02:13:21.783
37167
72356
answer