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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Python

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

Q&A

解決済

4回答

402閲覧

Pythonの内包表記(for if)について

Hashmore

総合スコア8

Python 3.x

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

Python

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

0グッド

0クリップ

投稿2017/11/28 08:12

Python初心者です。内包表記についての質問です。

空でない数字のリスト中から、重複の無いもののみを除外する課題の解決を試みました。

入力[1, 2, 3, 1, 3]→出力[1, 3, 1, 3]
入力[1, 2, 3, 4, 5]→出力[]

これに対して、次のようなコードを書きました。

lang

1def solve(data): 2 3 return data.remove(uni for uni in data if data.count(uni)==1)

引数dataのリストから、countで個数が1個だったもののみをremoveで取り除く、という処理を意図しています。しかし、[1, 2, 3, 1, 3]など数のリストを入力すると、

ValueError: list.remove(x): x not in list

とエラーが返ってきます。原因がわからないので、ご教授いただきたく思います。

なお、課題の解決自体は、次のコードで達成できました。

lang

1def solve(data): 2 3 for i in data[:]: 4 if data.count(i)==1: 5 data.remove(i) 6 7 return data

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

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

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

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

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

guest

回答4

0

python

1def solve(data): 2 return [k for k in data if data.count(k)>1] 3data = solve(data) 4print(data)

あまりよくない書き方ですが、もとのコードに忠実に行けば、

python

1def solve(data): 2 return [data.remove(k) for k in [uni for uni in data if data.count(uni)==1]] 3solve(data) 4print(data)

投稿2017/11/28 08:54

編集2017/11/28 09:02
mkgrei

総合スコア8560

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

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

Hashmore

2017/11/29 02:15

ありがとうございます。参考になります。 回答後半、「もとのコードに忠実な書き方」を実行してみると、リスト中に一つしかない数の個数のNoneからなるリストが返ってきます。kがdata中に一つしかない数を全て抽出できているようなので不思議です。なんとなく、dataから一部削除して残されたものではなく、dataから取り除いたものそのものを返そうとしているように思えます。
guest

0

原因についてはyhmrさんのとおり、対応方法についてはmkgreiさんのとおりでよいと思います。

ちょっと気になったので関数の引数内で内包表記した場合の型を確認してみました。
generatorのようですね。ジェネレータ式というのかな?
参考:pythonの内包表記を少し詳しく

Python

1def hoge(o): 2 print(type(o)) # <class 'generator'> 3 4data = [1,2,3,1,3] 5hoge(uni for uni in data if data.count(uni)==1)

投稿2017/11/28 09:25

編集2017/11/28 09:29
can110

総合スコア38266

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

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

mkgrei

2017/11/28 09:36

そうなのです。 なので、 data.remove(next(uni for uni in data if data.count(uni)==1])) をすると1個だけ削除できて、エラーが出るまで反復するとお望みの結果が得られます。 python3だとlistで囲むとgeneratorが実行されるので、謎のトリックを使っています。 削除しながらfor文を回すとだいたい大変なことになりますが、うまく動いているコードはちゃんとdata[:]を回していて、初心者とは思えない高度な実装になっています。
can110

2017/11/28 09:50

コメントありがとうございます。 質問後半、data[:]で別オブジェクトできてるのでなので○ですね。 見た目ヒヤヒヤなコードですが(w
mkgrei

2017/11/28 11:11

やらかしていた過去の嫌な思い出が蘇ります。 pythonは書き方が自由すぎて、細心の注意を払わないといけないのがたまにキズです。 よくわからないテクニックばかり身につきますね。
guest

0

ベストアンサー

list.remove()はイテラブルを引数に取らないからだと思います。

これがsum()のようなイテラブルを引数に取る関数だったら上手く動作しますが、list.remove()の中にジェネレータ式を書いてもダメですね。

ちなみにこれをジェネレータ式ではなく

python

1data.remove( [ uni for uni in data if data.count(uni)==1 ] )

のように配列内包で書いても同様に上手く動作しません。なぜならlist.remove()に渡される引数はリストであり、dataリストは要素にリストを持たないからです。

投稿2017/11/28 09:31

Lhankor_Mhy

総合スコア36104

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

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

0

[1, 2, 3, 4, 5]を入力として該当のsolve関数を実行した場合、リストからintの2ではなく、listの[2]を削除しようとしていることがエラーの原因ではないでしょうか。

投稿2017/11/28 09:10

yhmr

総合スコア53

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

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

Hashmore

2017/11/29 02:24

ありがとうございます。 データ型等について色々勉強してきましたが、solveの引数がジェネレータ式であるところまでは理解できました。ここでこのジェネレータ式の引数(リスト内包表記ではない)によって、intの2ではなくlistの[2]を削除する処理になっていることについて、よろしければもう少し詳しくお聞きしたいですが、よろしいでしょうか。
yhmr

2017/11/29 03:49

私の回答の、 > listの[2]を削除しようとしている という点が間違いです。 正しくは、他の皆様の回答やHashmoreさんのコメントにもあります通り、ジェネレータ式ですね。リスト内包表記と勘違いしておりました… 混乱させてしまい、大変申し訳ございません。 間違えた回答となっておりますため、低評価の程よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問