🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1882閲覧

二次元リストの平均値の算出。もっと綺麗なコードに書き換えたい

penpineapple

総合スコア2

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

1グッド

0クリップ

投稿2021/01/07 11:01

編集2021/01/07 13:18

以下のように数値以外の値が混入した二次元のリストから行ごとの平均値を算出し一次元のリストにその平均値を格納するプログラムを作成しています。

python

1li_2d = [[1, 2, 3, 4], 2 [1, 3, 5.5, 7], 3 [1, 2.5, 3, 'a'], 4 ['a', 3, 5, None]]

数値以外の値(文字列やNone)がある行はもちろんエラーになってしまうためIllegalNot Numberなど計算できなかったことを示す文字列を平均値の代わりに入れたいです。

以上のことを踏まえて下のようなプログラムを作成してみましたが、フラグ変数を利用しているためコードが少し長くなってしまいました。

  • 行ごとに平均値を算出するプログラム

python

1import statistics 2 3 4def is_num(val) -> bool: 5 return isinstance(val, int) or isinstance(val, float) 6 7 8def average_2d(li_2d: list) -> list: 9 result = [] 10 for li in li_2d: 11 li_1d_temp = [] 12 flag_skip = False 13 for elem in li: 14 if is_num(elem): 15 li_1d_temp.append(elem) 16 else: 17 result.append('illegal') # ここの文字はなんでもいい。でも何か文字は入れたい 18 flag_skip = True 19 break 20 if not flag_skip: 21 result.append(statistics.mean(li_1d_temp)) 22 return result 23
  • 使用例

python

1if __name__ == '__main__': 2 li_2d_no1 = [[1, 2, 3, 4], 3 [1, 3, 5.5, 7], 4 [1, 2.5, 3, 'a'], 5 ['a', 3, 5, None]] 6 7 li_2d_no2 = [[1, 2, 3, 4, 5, 6], 8 [None, 3, 5, 7, 9, 11], 9 [1.5, 2.5, 3, 4, 5, 6.5]] 10 print('No1', average_2d(li_2d_no1)) 11 print('No2', average_2d(li_2d_no2)) 12

result

1No1 [2.5, 4.125, 'illegal', 'illegal'] 2No2 [3.5, 'illegal', 3.75]

これでも一応期待通りに動くのでそのまま利用してもいいのですが、できればもっとスマートな方法で綺麗なコードにしたいです。
なにか他にいい方法はないでしょうか。

######補足

  • 実際に利用するときはかなり長いリストを使う可能性があるので実行速度が遅くなるような例外処理は使いたくありません。
  • リストではなくNumpy配列でも大丈夫です。

######環境
python3.8.5

A_kirisaki👍を押しています

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

tryを使うと、こんな感じです。

python

1>>> def avr(a): 2... try: 3... return float(sum(a))/len(a) 4... except Exception: 5... return 'illegal' 6... 7>>> def average_2d(a): 8... return [avr(x) for x in a] 9... 10>>> li_2d = [[1, 2, 3, 4], 11... [1, 3, 5.5, 7], 12... [1, 2.5, 3, 'a'], 13... ['a', 3, 5, None]] 14>>> 15>>> average_2d(li_2d) 16[2.5, 4.125, 'illegal', 'illegal']

pythonで好まれるコーディングスタイルです。

公式ドキュメントの用語集には、EAFPとして書かれています。
「認可をとるより許しを請う方が容易 (easier to ask for forgiveness than permission)」の略です。
やってみてだめだったら、後処理をした方が楽だよ、だと解釈しています。

投稿2021/01/07 12:05

編集2021/01/07 12:16
ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

penpineapple

2021/01/07 14:14 編集

回答ありがとうございます。 例外処理使うとこんなにスッキリするんですね。びっくりしました。 EAFPという用語を今まで知らなかったので少し調べてみたのですが、PythonはC系やJavaと違い例外の処理のコストがそこまで大きくないみたいですね。ループ中の例外はさらに最適化されていて実行速度にほとんど影響しないとか。 PythonはJavaやC系とは違いインデントが重要な言語なので、インデントを多用するif文よりもtry-exceptの方が好まれる、というのもあるんでしょうかね。 コードの簡略化だけでなくコーディングスタイルについても勉強になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問