質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

Pythonのコードの中で分からない表現があります。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 208

amaturePy

score 97

Python3で書かれたコートの中で一部理解出来ない表現があります。
以下のコードは別ファイルから引数として渡された情報の中から遷移元id(ind_row)と選択肢(ind_row2/テキスト情報)の2種類のカラム情報を処理しています。
その中で以下の一部のコードについて自分の解釈が合っているか確認頂けたら幸いです。
単純なPythonの実力不足だとは思うのですが、少しでも理解して行きたくご質問させて頂きたいです。

①8行目:if x!=""xの要素が空欄出ないなら=存在したら以降の処理を実行

②11行目:if len(row_new1)>1:row_new1(row_newをsplitした物)の要素が1以上である場合

③12〜14行目:
if len(row_new1)!=len(b1):
  if len(b1)==1:
   c = row_new1[0] 

row_new1(選択肢)とb1(id)の数が一致しない場合でb1(id)の要素数が1つの場合は、
変数cをind_row1の0番目の要素と定義する

④19行目:c = row_new1[b1.index(x)]:←ここが一番理解出なかったです。
前にb1(id)をfor文でxという変数としてループ処理しているので、以下の形になるのかと予想しました。
----------
key|index←b1.index(x)??
1   100020003000
---------
このrow_new1ごとの上記indexを取得している?
function.py

def _id_choice(fr, ind_row, ind_row2):
  len0 = 0
  for row in fr:
    if len0>0:
      a, b = row[0], row[ind_row]
      b1 = b.split("/")
      for x in b1:
        if x!="":
          row_new = _replace(row[ind_row2])
          row_new1 = row_new.split("/")   ### check later! ###
          if len(row_new1)>1:
            if len(row_new1)!=len(b1):
              if len(b1)==1:
                c = row_new1[0]         ### choose one of choices! ###
                c = c[:trunc]           ### truncation! ###
                f2.write("%s/%s\t%s\r\n" % (x,a,c))  # check later
              else:
                print("different numbers of items at ID: %s(%s)" % (row[0],name))
                c = row_new1[b1.index(x)]  # check later
                c = c[:trunc]           ### truncation! ###
                f2.write("%s/%s\t%s\r\n" % (x,a,c))  # check later
            else:
              c = row_new1[b1.index(x)]
              c = c[:trunc]           ### truncation! ###
              f2.write("%s/%s\t%s\r\n" % (x,a,c))
          else:
            c = row_new1[0]
            c = c[:trunc]           ### truncation! ###
            f2.write("%s/%s\t%s\r\n" % (x,a,c))
    len0 += 1
  return len0
deal_csv.py

  if switch == 1:
    f0, fr0 = _load_file(file0)
    file2 = "./id_choice.tsv"
    f2 = codecs.open(file2, "w", "utf-8")
    f2.write("%s\t%s\r\n" % ("ID_bef/aft","choice"))
    trunc = 100  # trancation length
    len2 = _id_choice(fr0,2,3)  # depends on csv file
    f0.close()
    f2.close()
csvファイルカラム構造

id|message|遷移元id|選択肢|
1 xxxxxx  30/31/32  選択肢1
2  xxxxxx  40/41/42  選択肢2
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • can110

    2020/07/04 17:37

    そのまま実行できるコードとデータ
    できれば今回の質問で触れられていないfr,f2,name,truncを取り除いて
    簡略化したコードを提示していただけると回答得られやすいと思います。

    キャンセル

  • amaturePy

    2020/07/04 20:00

    そうですね。分かりにくいですよね。
    ありがとうございます。

    キャンセル

回答 1

checkベストアンサー

+1

④19行目:c = row_new1[b1.index(x)]:←ここが一番理解出なかったです。

列2: b1=["30","31",32"]
列3: row_new1=["選択肢1.1","選択肢1.2","選択肢1.3"]

という状態のときに、xは30→31→32と変化していく訳ですが、index()は今処理しているxがリストの何番目に来るか返す関数ですので、0→1→2と変化します。そのためcはrow_new1[0]→ row_new1[1]→row_new1[2]と変化し、結果として選択肢1.1→選択肢1.2→選択肢1.3と変化することになります。

ソースコードを解析する際のコツとしては

デバッガを使え!

でしょうか。VSCodeやPycharmなどのエディタでは、ソースコードを1行ずつ追えて変数をウォッチ可能なデバッガが使えます。最初はデバッガの準備が面倒かも知れませんが、このようなソースコードを解析する作業が多いのであれば、デバッガの使い方を習得する方が近道です。

単純なPythonの実力不足だとは思うのですが

いえ、これはソースコードの方も難解です。ソースコードが読みにくい理由は

  • インデントが深い
  • 意味のない代入が多い(a, b = row[0], row[ind_row]やc = row_new1[0])
  • 変数名から内容が予測できない
  • 同じ概念を持つ変数名が全く異なる変数名で定義されている(b1とrow_new1)
  • 対になっていない(ind_rowとind_row2)
  • 不要なif分が多い、処理をまとめていない
  • ループの外で実施すべきものがループの中に入っている

参考までにほとんど等価なコードを作ってみました(スラッシュは全角から半角にしています)。

def _id_choice(fr, ind_row1, ind_row2):
    len0 = 1
    for row in fr[1:]:
        b1 = row[ind_row1].split("/")
        b2 = _replace(row[ind_row2]).split("/")
        if len(b1) != len(b2) and len(b1) != 1 and len(b2) > 1:
            print("different numbers of items at ID: %s(%s)" % (row[0], name))
        for x in b1:
            if x == "":
                continue
            if len(b2) > 1:
                f2.write("%s/%s\t%s\r\n" % (x, row[0], b2[b1.index(x)][:trunc]))
            else:
                f2.write("%s/%s\t%s\r\n" % (x, row[0], b2[0][:trunc]))
        len0 += 1
    return len0

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/06 01:35 編集

    頂いたコードも読ませて頂きまして理解しました。すごく読みやすい。。。。
    そのように処理されているのですね。頭で理解したとしても頂いたご説明のように言語化するのも私だと頭の中でこんがらがりそうです(笑)。とても参考になりました!Pycharmのデバッガはやはり重要ですね。Pycharmを使用してみます。
    比較的難しいコードでもスキルのある方はこのように書き換えまでできるのですね。驚きました。
    書き換えて頂いた方も参考にさせて頂きます!!
    ありがとうございました!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る