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

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

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

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

Q&A

解決済

3回答

8413閲覧

Pythonによる”uniq”実装

chijan

総合スコア24

Python 3.x

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

3グッド

0クリップ

投稿2016/02/14 06:24

目的:
Pythonでunixコマンドのuniqのような、配列から重複を削除するスクリプトを作りたいです。

方法:
http://lightson.dip.jp/zope/ZWiki/102_e9_85_8d_e5_88_97_e3_81_8b_e3_82_89_e9_87_8d_e8_a4_87_e3_81_99_e3_82_8b_e8_a6_81_e7_b4_a0_e3_82_92_e5_8f_96_e3_82_8a_e9_99_a4_e3_81_8f
にある方法で実装

結果:
[1,1,2,3,4,4,5]や['spam','spam','spam','spam','baked_beens']のような1次元配列ではうまくいきました。
しかし、[[1,2,3],[1,2,3],[7,8,9]]といった2次元配列では、
item not in seenのところで
TypeError:unhashable type 'list'
というエラーが出ました。

考察:
てきとうなsetとして

Python

1s=set([[1,2,3],[4,5,6]])

としたところ、結果と同様のエラーが出たので、set()の仕様が原因なのだろうかと考えております。

質問:
上述の1次元配列に加えて、2次元以上の配列にも対応する([[1,2,3,],[1,2,3],[7,8,9]]を[[1,2,3],[7,8,9]]とする、など)ような"uniq"はどのように実装すればよろしいのでしょうか?

よろしくお願いします。

arly_times, cry_4_the_moon, argius👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

TypeError: unhashable type: 'list'というエラーが出ているので、リスト(list)はハッシュにできない型ということですね。

hashableについては、下記の記事に詳しく書いてありました。

Python における hashable - Qiita
http://qiita.com/yoichi22/items/ebf6ab3c6de26ddcc09a

大雑把にいってしまうと、セット(set)はhashによる実装(hash set)で、immutableでないオブジェクトはhashableになり得ないのでリストはセットの値に使えない、ということのようです。

...

ではどうしたら良いのかというと、タプル(tuple)を使います。
タプルはimmutableでhashableなので、セットに使えます。
listをタプルに変換するには、tuple(list)とします。

  • コード例

python

1list1 = [1, 2, 3] 2list2 = [4, 5, 6] 3list3 = [1, 2, 3] 4 5s=set([tuple(list1), tuple(list2), tuple(list3)]) 6print(s) # => {(4, 5, 6), (1, 2, 3)}

投稿2016/02/14 06:49

argius

総合スコア9388

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

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

chijan

2016/02/14 12:44 編集

tupleというものがあるのですね! item=tuple(item)としてから item not in seenを判定するとうまくいきました。 エラーの原因まで解説して下さりとても助かりました。 ありがとうございます!
guest

0

すでに解決されているようですが、一応簡単な方法を。

def uniq(l): res = [] # 結果を格納するリストを用意 for item in l: if item not in res: # 結果のリストに含まれていない要素だったら res.append(item) # 結果のリストに追加 return res input_list = [[1, 2, 3], [1, 2, 3], [7, 8, 9], 1, 2, 1] print(uniq(input_list)) # [[1, 2, 3], [7, 8, 9], 1, 2]

パフォーマンス的にはすでに他の回答者の方が書かれている方法の方がいいと思います。

投稿2016/02/17 12:05

Miyako

総合スコア142

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

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

0

参考情報;

...
[x for i, x in enumerate(a) if i == a.index(x)]
b = [];[b.append(x) for x in a if not x in b];b
...

試してみました。

$ python3 Python 3.5.1 (default, Dec 7 2015, 21:59:10) [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.1.76)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> a = [1,1,2,3,4,4,5] >>> [x for i, x in enumerate(a) if i == a.index(x)] [1, 2, 3, 4, 5] >>> a = ['spam','spam','spam','spam','baked_beens'] >>> [x for i, x in enumerate(a) if i == a.index(x)] ['spam', 'baked_beens'] >>> a = [[1,2,3],[1,2,3],[7,8,9], 1, 2, 1] >>> [x for i, x in enumerate(a) if i == a.index(x)] [[1, 2, 3], [7, 8, 9], 1, 2] >>>

投稿2016/02/14 09:24

katoy

総合スコア22324

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

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

chijan

2016/02/14 12:43

set()を使わないようなそういうやり方もあったのですね。 enumerate()というものを使うのですか……勉強になりました、ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問