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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

Python 3.x

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

Python

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

Q&A

解決済

5回答

560閲覧

python リスト 要素変動 エラー回避 簡潔なコード

tttkkk

総合スコア38

Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

Python 3.x

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

Python

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

0グッド

0クリップ

投稿2022/09/01 22:41

エラーが出ることが予測されるコードで
エラーを回避しようとするコードにしようとした場合、
冗長になってしまうのですが、良い対処方法を教えていただけないでしょうか。

実行環境は以下の通りです。
Windows10
google colab
Python 3.7.13

以下のようにリストの各要素に対して処理をするコードがあるとします。
サンプルコードのように a, b, c では要素がある以上、できるだけ値を入れたいと考えています。
ポイントはリストの要素の数が一定ではないということです。

下記のコード①ですと
lists の要素数は4個ですが、これが処理の流れによっては変動してしまいます。
(しかし大体は4個程度を想定しており、10個20個になることはありません。)
コード①は4個の要素に対して、それぞれ処理をしているので、エラーになることはありません。

python

1# ① 2lists = [2947, 683, 1057, 9301] 3a = lists[0] / lists[1] 4b = lists[1] / lists[2] 5c = lists[2] / lists[3] 6print(a, b, c)

しかしリストの要素数が減り、例えば2個などになってしまうと
コード①ではエラーが出てしまいます。
その回避方法としてコード②のように
if で場合分けをすることを考えたのですが、
変動する要素数それぞれで場合分けをしなくてはならず、冗長になってしまいます。
(コード②では要素数4個までの場合分けで止めています。)

python

1# ② 2lists = [2947, 683] 3if len(lists) == 1: 4 a = '-' 5 b = '-' 6 c = '-' 7elif len(lists) == 2: 8 a = lists[0] / lists[1] 9 b = '-' 10 c = '-' 11elif len(lists) == 3: 12 a = lists[0] / lists[1] 13 b = lists[1] / lists[2] 14 c = '-' 15elif len(lists) == 4: 16 a = lists[0] / lists[1] 17 b = lists[1] / lists[2] 18 c = lists[2] / lists[3] 19print(a, b, c)

try except の使用も考えてはみましたが、
結局 a, b , c それぞれにできるだけ値を入れたいというのを考えと、
exceptの部分でコード②のような場合分けをしないといけないことになってしまいました。

上記のような処理の場合、a, b, c に値はできる限りいれつつも、より簡潔に(一回一回場合分けをしなくても済むような)エラー対処をできる構文はこざいますでしょうか。
長くて分かりにくい部分もあり、申し訳ございませんが、教えて頂けますと幸いです。

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

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

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

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

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

guest

回答5

0

その a、b、c もリストにしましょうよ
んで、listsの要素数でループさせたらいいでしょ

投稿2022/09/01 23:07

編集2022/09/01 23:08
y_waiwai

総合スコア87774

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

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

0

以下のような感じでどうでしょう。

Python

1for lists in [[2947, 683, 1057, 9301],[2947,683]]: 2 lists = lists[:4] 3 ret = ['-','-','-'] 4 for i in range(len(lists)-1): 5 ret[i] = lists[i] / lists[i+1] 6 a, b, c = ret 7 print(a, b, c) 8 9# 4.314787701317716 0.6461684011352885 0.11364369422642727 10# 4.314787701317716 - -

投稿2022/09/01 22:54

can110

総合スコア38266

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

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

0

ベストアンサー

ひとつの考え方として、

  • lists[2947, 683][2947, 683, 1057] などのように要素数が4未満だった場合には「データが欠損している」と考えて、何か別の値で欠損分を補完して長さを4に合わせてから主目的の計算を行う

というアプローチがあると思います。

この考え方でいくとすると、何で補完するか?ということになりますが、今回の場合は

  • 除算の除数、あるいは被除数と除数の両方にその値が使われたときに、エラーにはならないが結果が無効な値になるような値

が望ましいですが、そのような値としては math モジュールの nan を使えます。

python

1from math import nan

具体的には基準になる長さを

python

1LEN = 4

としておいて、与えられた lists に対して

python

1lists = lists + [nan for _ in range(LEN-len(lists))]

とすると、lists は基準の長さに足りない分のnanが後ろに詰められたリストになります。

こうしておくと、隣り合った要素どうしで除算した結果のリストを得るにはたとえば

python

1[*map(lambda x: x[0]/x[1], zip(lists, lists[1:]))]

とすればよいです。有効な数値をnan で割ったり nannanで割ってもエラーにはならず、結果もまた nan になってくれるという所がミソです。

以下は隣り合った要素どうしで除算した結果のリストを得るところを関数にして、長さが1から4までのデータで試すコードです。

python

1from math import nan 2 3 4LEN = 4 # 基準となるデータ長 5 6def quotientsOfNeighbors(lists): 7 lists = lists + [nan for _ in range(LEN-len(lists))] # 基準の長さに足りない分を nan で補完する 8 return [*map(lambda x: x[0]/x[1], zip(lists, lists[1:]))] # 隣り合う要素どうしで除算した結果のリストを返す 9 10 11samples = [ 12 [2947], 13 [2947, 683], 14 [2947, 683, 1057], 15 [2947, 683, 1057, 9301] 16] 17 18for lists in samples: 19 a, b, c = quotientsOfNeighbors(lists) 20 print('lists:%s, a:%.3f, b:%.3f, c:%.3f' % (lists, a, b, c)) 21

lists:[2947], a:nan, b:nan, c:nan
lists:[2947, 683], a:4.315, b:nan, c:nan
lists:[2947, 683, 1057], a:4.315, b:0.646, c:nan
lists:[2947, 683, 1057, 9301], a:4.315, b:0.646, c:0.114

投稿2022/09/02 02:28

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tttkkk

2022/09/02 09:54

nanを使う方法は全く頭にありませんでした。 新しい知識をありがとうございます。 初心者すぎる質問でしたら申し訳ないのですが、 lists = lists + [nan for _ in range(LEN-len(lists))] という分において、 for の後に _ がございます。 この _ はどのような意味合いで使用しているのでしょうか。 お手数ですが教えていただけると助かります。
退会済みユーザー

退会済みユーザー

2022/09/02 10:27 編集

たとえば 0 始まりで偶数を 5 個含むリストを作りたい場合に、リスト内包表記では [n * 2 for n in range(5)] とすればよいですね。この場合 n は 0, 1, 2, 3, 4 と変化していき、これらに応じた n * 2 がリストの要素になるわけです。では同じく n は 0, 1, 2, 3, 4 と変わるけれども、要素は 1 で変わらないようなリスト [1, 1, 1, 1, 1] を作るにはどうすればよいかというと、さきほどの n * 2 が (nを含まない定数の) 1 になればよいので [1 for n in range(5)] によって 1 を 5個含むリストを作ることができます。 そしてこの場合、変数 n は使われていませんが、使われない変数を表すときに変数名を _ だったり または _ 始まりの例えば _n という名前にするのが慣例になっていることがあります。 これに倣うと [1 for n in range(5)] よりも、 [1 for _ in range(5)] と書くのがより良いコードと言えることになります。回答にあるコードの [nan for _ in range(LEN-len(lists))] の _ もそれに従ったものです。 ちなみに 1 を5個含むリストを作るには [1] * 5 と書く方が手短かに済みますね。これを使うと、[nan for _ in range(LEN-len(lists))] は以下で済みます。 [nan] * (LEN-len(lists))
tttkkk

2022/09/04 05:12

コメントの確認が遅くなってしまいました。 ご丁寧にどうもありがとうございます。 また一つ勉強になりました。 実際に行いコードに実装してみまして試させていただきます。
guest

0

zip関数を使うといいですよ。

python

1>>> lists = [2947, 683, 1057, 9301] 2>>> print(*[a / b for a, b in zip(lists, lists[1:])]) 34.314787701317716 0.6461684011352885 0.11364369422642727 4>>> lists = [2947, 683] 5>>> print(*[a / b for a, b in zip(lists, lists[1:])]) 64.314787701317716

不足分を - で補う場合:

def calc(data, size=3): values = [a / b for a, b in zip(lists, lists[1:])] return values + ['-'] * (size - len(values)) lists = [2947, 683, 1057, 9301] a, b, c = calc(lists) print(a, b, c) lists = [2947, 683] a, b, c = calc(lists) print(a, b, c)

text:実行結果

14.314787701317716 0.6461684011352885 0.11364369422642727 24.314787701317716 - -

投稿2022/09/02 01:19

編集2022/09/02 03:36
shiracamus

総合スコア5406

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

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

0

苦肉の策ではあるものの、守備範囲が広い案として。

Python

1def if_error(func, default): 2 try: 3 return func() 4 except Exception: 5 return default 6 7a = if_error(lambda: lists[0] / lists[1], '-') 8b = if_error(lambda: lists[1] / lists[2], '-') 9c = if_error(lambda: lists[2] / lists[3], '-')

投稿2022/09/01 23:24

LouiS0616

総合スコア35660

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問