61237


python初心者です。

[code]

    A = [[a,0,0,0,0],[b,1,0,0,0],[c,0,1,0,0],[a,0,0,0,1]]
    
[/code]

以下がAというリストに対して行いたい処理です。

①それぞれの要素の０番目（a,b,c）を照合  
②重複するものがあれば（例ではaが重複）、今度は1番目～4番目の要素を照合  
③０番目は同じだが、1~4番目が完全一致しないものをリスト化して抽出する

以下のようなリストを作りたいです。

[code]

    result = [[a,0,0,0,0,],[a,0,0,0,1]]
    
[/code]

知識不足ながらプログラム案を考えてみました。

[code]

    A = [[a,0,0,0,0],[b,1,0,0,0],[c,0,1,0,0],[a,0,0,0,1]]
    result = []
    for i in A[?][1]:
        if i==A[?][1]:
            result.append(i)
    
[/code]

これにどのような変更を加えたら良いのか分かりません。  
ご教示お願い致します。


CC BY-SA 4.0
2019-12-08T08:19:56.987
61234
2019-12-09T17:46:50.133
2019-12-08T08:38:20.853
36978
36978
question
python
リスト内の要素を照合して抽出したい


これらの記事を参考に：  
[Pythonで2次元配列の重複行を一発で削除する](https://qiita.com/uuuno/items/b714d84ca2edbf16ea19)  
[Pythonのスライスによるリストや文字列の部分選択・代入](https://note.nkmk.me/python-slice-usage/)  
[Pythonでリスト（配列）から重複した要素を削除・抽出](https://note.nkmk.me/python-list-unique-
duplicate/)  
[PythonのCounterでリストの各要素の出現個数をカウント](https://note.nkmk.me/python-collections-
counter/)  
[Pythonのin演算子でリストなどに特定の要素が含まれるか判定](https://note.nkmk.me/python-in-basic/)

(当初間違った物を投稿しましたが何とか修正して)こんな感じで処理出来ます。  
データは @metropolis さんの物をコピーさせてもらいました。

[code]

    # @metropolis さんのデータをコピー
    A = [
      ['c', 0, 1, 0, 0],
      ['d', 1, 1, 0, 1],
      ['a', 0, 0, 0, 0],
      ['b', 1, 0, 0, 0],
      ['c', 0, 1, 0, 0],
      ['a', 0, 0, 0, 1],
      ['b', 1, 0, 0, 0],
      ['d', 1, 0, 0, 1],
    ]
    
    # 重複除去した後、ソート
    B = list(map(list, set(map(tuple, A))))
    B.sort()
    
    # 各行の先頭の要素だけ抽出してリスト化
    C = [row[:1] for row in B]
    C = sum(C, [])
    
    # 複数存在する要素を抽出してセット化
    D = [x for x in set(C) if C.count(x) > 1]
    D = set(D)
    
    # 先頭の要素が複数存在する行だけ抽出して最終結果とする
    result = [row for row in B if row[0] in D]
    
[/code]

* * *

@letrec さんの処理に「やられた！」感があったので触発されて作ってみました。  
ただ、重複除去は上の1行で出来る奴でやった方が見通しが良いと思うのでそちらを使います。  
データは同じく @metropolis さんの物を使うということで省略。

[code]

    A = list(map(list, set(map(tuple, A)))) # 先に重複除去
    A.sort()
    
    result = []
    work = []
    prev = A[0]       # あらかじめ1つ取得・格納
    work.append(prev) #
    
    for i in range(1,len(A)): # 2つ目から始める
        row = A[i]
        if prev[0] != row[0]:       # 先頭データが変わった時
            if len(work) > 1:       # 2つ以上のデータがある時
                result.extend(work) # 結果に追加
    
            work = []               # 作業用配列クリア
    
        prev = row                  # 直前データ更新
        work.append(row)            # 作業用配列に追加
    
    if len(work) > 1:       # 2つ以上の未処理データがある時
        result.extend(work) # 結果に追加
    
[/code]

* * *

**追記**  
実データのリストではなく、インデックスのリストを作成する方法を考えてみました。

[code]

    index = []
    work = []
    prev = A[0][0] # あらかじめ最初の要素を1つ取得・格納
    work.append(0) #
    
    for i in range(1,len(A)): # 2つ目から始める
        if prev != A[i][0]:         # 先頭データが変わった時
            if len(work) > 1:       # 2つ以上のデータがある時
                index.extend(work)  # 結果に追加
    
            work = []               # 作業用配列クリア
            prev = A[i][0]          # 直前データ更新
    
        work.append(i)              # 作業用配列に追加
    
    if len(work) > 1:       # 2つ以上の未処理データがある時
        index.extend(work)  # 結果に追加
    
[/code]


CC BY-SA 4.0
2019-12-08T09:54:01.790
61237
2019-12-09T17:46:50.133
2019-12-09T17:46:50.133
26370
26370
61234
answer


「内容が同一のリストを単一化(uniquify)」して、「リストの最初(0番目)の要素が同一の複数のリストを抽出」ということかと思います。

[code]

    from itertools import groupby
    from operator import itemgetter
    
    A = [
      ['c', 0, 1, 0, 0],
      ['d', 1, 1, 0, 1],
      ['a', 0, 0, 0, 0],
      ['b', 1, 0, 0, 0],
      ['c', 0, 1, 0, 0],
      ['a', 0, 0, 0, 1],
      ['b', 1, 0, 0, 0],
      ['d', 1, 0, 0, 1],
    ]
    
    [
      v for v in
        map(lambda x: list(x[1]),
            groupby(
              sorted(map(list, set(map(tuple, A))),
                     key=itemgetter(0)),
              key=itemgetter(0)))
      if len(v) > 1
    ]
    
    ## 出力結果
    [[['a', 0, 0, 0, 1], ['a', 0, 0, 0, 0]], [['d', 1, 1, 0, 1], ['d', 1, 0, 0, 1]]]
    
[/code]


CC BY-SA 4.0
2019-12-08T09:58:57.860
61238
2019-12-08T09:58:57.860
61234
answer


ソートすることで、0番目の要素が等しいものが一箇所に並び、かつ完全に一致する要素は隣り合うため順番に見比べていくことで所望の結果が得られます。

[code]

    A.sort()
    
    result = []
    
    l = 0
    while l < len(A):
        r = l + 1
        temp = [A[l]]
        while r < len(A) and A[l][0] == A[r][0]:
            # 一つ前の要素と等しいような要素は追加しない
            if A[r] != A[r - 1]:
                temp.append(A[r])
            r += 1
    
        if len(temp) >= 2:
            result.append(temp)
    
        l = r
    
    print(result)
    
    
[/code]


CC BY-SA 4.0
2019-12-08T14:46:13.560
61242
2019-12-08T14:46:13.560
13199
61234
answer