ウッドチャックの穴掘り記

知りたくなったら掘るしかない

配列にある数字の数を数える[Python 3.0]

f:id:aisakakun:20160305111529j:plain

 

今回は、配列の中に複数個存在する数字以外は配列から削除するというプログラムです。

例えば、このような配列

a = [1,2,3,4]

だと、出力は

a = []

となるようにするということです。

 

この問題を見て最初に思いついたのがこちら

In [2]: def test(data):

   ...:          for i in data:

   ...:                if data.count(i) < 2:

   ...:                   data.remove(i)

   ...:          return data

これでいけそうな気もするのですが、

これで

In [3]: a = [1,2,3,4]

というのを引数とすると、

In [4]: test(a)

Out[4]: [2, 4]

と出力されてしまい、なぜか上手くいきません。

原因を調べて見たのですが、わからなかったため、

教えていただけますと幸いです。

 

そして、このアプローチが無理そうなのが分かったので別の方法で

やってみると成功しました。

それがこちらです。

今回、初めて用いた「Counter」

その中でもmost_common()を用いておりますが、

most_common() は文字と、その要素数を返してくれるため

使用しました。

詳しくは、こちらのサイトを見ていただければ分かりやすいと思います。

8.3. collections — 高性能なコンテナ・データ型 — Python 2.7.x ドキュメント

 

求められた出力結果は出せたのですが、いまいち冗長。

なので、他の人のを見てみると...

解説不要なくらいシンプルで分かりやすいプログラムです。

瞬時にこのくらい思いつくように精進します。

 

(追記 2016-13時) 

解決事項を追記します。

 

この問題を見て最初に思いついたのがこちら

In [2]: def test(data):

   ...:          for i in data:

   ...:                if data.count(i) < 2:

   ...:                   data.remove(i)

   ...:          return data

これでいけそうな気もするのですが、

これで

In [3]: a = [1,2,3,4]

というのを引数とすると、

In [4]: test(a)

Out[4]: [2, 4]

と出力されてしまい、なぜか上手くいきません。

の部分に対し、id:h-miyako さんよりコメントをいただけました。

感謝いたします。

リストの要素をループ中で削除しているのが原因です。

data = [1,2,3,4]
for i in data:
data.remove(i)

これの処理を追っていくと、以下のようになります。

dataの一番目の要素をiに代入(i=data[0]=1)
dataから1を削除(data=[2,3,4])
dataの二番目の要素をiに代入(i=data[1]=3)#ここでずれる
dataから3を削除(data=[2,4])
dataの三番目の要素をiに代入しようとするが、dataには三番目の要素はないのでforループ終了

最終的にdata=[2,4]となります。

これを避けるためには、元のデータをループ中で変更するのではなく、出力用のリストを別に用意しておけばいいです。

result = [ ]
for i in data:
if data.count(i) != 1:
result.append(i)
return result

となります。

とのことでした。なるほど。納得しました。