ほとんどの場合、リストに重複があるかどうかをチェックするプログラムを作成する必要があります。リストに重複がある場合はそれらを削除し、重複または削除したアイテムを含む新しいリストを返します。これは私が持っていることですが、正直なところ私は何をすべきかわからない。
def remove_duplicates():
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
for t in t2:
t.append(t.remove())
return t
項目の一意のコレクションを取得するための一般的な方法は、 set
を使用することです。集合は、 順不同 / はっきりした オブジェクトの集合です。任意のイテラブルから集合を作成するには、単にそれを組み込みの set()
関数に渡すことができます。後で実際のリストが必要になった場合は、同様に list()
関数にセットを渡すことができます。
次の例は、あなたがやろうとしていることをすべて網羅しているはずです。
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]
例の結果からわかるように、元の順序は維持されません。上記のように、集合自体は順序付けられていないコレクションなので、順序は失われます。セットをリストに戻すときには、任意の順序が作成されます。
順序があなたにとって重要であるならば、あなたは異なるメカニズムを使わなければならないでしょう。これに対する非常に一般的な解決策は、挿入時にキーの順序を維持するために OrderedDict
に頼ることです。
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]
これには、最初に辞書を作成し、次にそれからリストを作成するというオーバーヘッドがあります。そのため、実際に注文を保存する必要がない場合は、セットを使用することをお勧めします。重複を削除するときに順序を維持するための詳細および代替方法については、 この質問 を参照してください。
最後に、set
とOrderedDict
の両方の解決法では、あなたのアイテムは hashable である必要があります。これは通常彼らが不変でなければならないことを意味します。ハッシュ可能ではないアイテム(リストオブジェクトなど)を処理する必要がある場合は、基本的に入れ子になったループ内のすべてのアイテムを他のすべてのアイテムと比較する必要がある、低速のアプローチを使用する必要があります。
Python 2.7 では、イテラブルから元の順序で複製を削除する新しい方法は、次のとおりです。
>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
Python 3.5 では、OrderedDictはCを実装しています。私のタイミングでは、これがPython 3.5のさまざまなアプローチの中で最速でも最短でもあることを示しています。
Python 3.6 では、通常の辞書は規則正しくコンパクトになりました。 (この機能はCPythonとPyPyには有効ですが、他の実装には存在しないかもしれません)。これにより、順序を維持しながら、最短の重複排除の新しい方法が得られます。
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
Python 3.7 では、通常の辞書はすべての実装にわたって順序付けられていることが保証されています。 だから、最短かつ最速の解決策は次のとおりです。
>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
それはワンライナーです:list(set(source_list))
がうまくいくでしょう。
set
は、重複する可能性がないものです。
更新:順序を保存する方法は2行です。
from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()
ここではOrderedDict
がキーの挿入順序を覚えていて、特定のキーの値が更新されたときにそれを変更しないという事実を使います。値としてTrue
を挿入していますが、何でも挿入できます。値は使用されていません。 (set
は無視された値を持つdict
とよく似た働きをします。)
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> s = []
>>> for i in t:
if i not in s:
s.append(i)
>>> s
[1, 2, 3, 5, 6, 7, 8]
あなたが順序を気にしないのなら、ただこれをしてください。
def remove_duplicates(l):
return list(set(l))
set
は重複しないことが保証されています。
L
内の重複の最初の要素の順序を保持する新しいリストを作成する
newlist=[ii for n,ii in enumerate(L) if ii not in L[:n]]
例えばif L=[1, 2, 2, 3, 4, 2, 4, 3, 5]
ならnewlist
は[1,2,3,4,5]
になります
これは、新しい要素が追加される前にリストに表示されていないことを確認します。 また輸入は必要ありません。
別のやり方:
>>> seq = [1,2,3,'a', 'a', 1,2]
>> dict.fromkeys(seq).keys()
['a', 1, 2, 3]
同僚が彼のコードの一部として、今日のコードレビューのために私に受け入れられた答えを送ってきました。この解決策を試してみました(私は set を使って検索時間を短縮しています)
def ordered_set(in_list):
out_list = []
added = set()
for val in in_list:
if not val in added:
out_list.append(val)
added.add(val)
return out_list
効率を比較するために、100個の整数のランダムサンプルを使用しました。
from random import randint
x = [randint(0,100) for _ in xrange(100)]
In [131]: len(set(x))
Out[131]: 62
これが測定結果です。
In [129]: %timeit list(OrderedDict.fromkeys(x))
10000 loops, best of 3: 86.4 us per loop
In [130]: %timeit ordered_set(x)
100000 loops, best of 3: 15.1 us per loop
それでは、setが解から削除されたらどうなりますか?
def ordered_set(inlist):
out_list = []
for val in inlist:
if not val in out_list:
out_list.append(val)
return out_list
結果は OrderedDict ほど悪くありませんが、それでも元のソリューションの3倍以上です。
In [136]: %timeit ordered_set(x)
10000 loops, best of 3: 52.6 us per loop
PandasとNumpyを使った解決策もあります。どちらもnumpy配列を返すため、リストが必要な場合は .tolist()
関数を使用する必要があります。
t=['a','a','b','b','b','c','c','c']
t2= ['c','c','b','b','b','a','a','a']
Pandas関数を使う unique()
:
import pandas as pd
pd.unique(t).tolist()
>>>['a','b','c']
pd.unique(t2).tolist()
>>>['c','b','a']
派手な関数を使う unique()
。
import numpy as np
np.unique(t).tolist()
>>>['a','b','c']
np.unique(t2).tolist()
>>>['a','b','c']
numpy.unique()も値 をソートすることに注意してください。そのため、リストt2
はソートされて返されます。順序を保存したままにしたい場合は、 この答え のように使用します。
_, idx = np.unique(t2, return_index=True)
t2[np.sort(idx)].tolist()
>>>['c','b','a']
解決策は他の解決策に比べるとそれほど洗練されていませんが、pandas.unique()やnumpy.unique()と比較すると、入れ子になった配列が選択した1つの軸に沿って一意であるかどうかも確認できます。
シンプルで簡単
myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanlist = []
[cleanlist.append(x) for x in myList if x not in cleanlist]
出力:
>>> cleanlist
[1, 2, 3, 5, 6, 7, 8]
私は自分のリストに辞書を書いていたので、私は上記のアプローチを使うことができませんでした。私はエラーを得ました:
TypeError: unhashable type:
もしあなたが order そして/またはいくつかの項目に気をつけているのであれば 手に負えない それでは、これが便利かもしれません:
def make_unique(original_list):
unique_list = []
[unique_list.append(obj) for obj in original_list if obj not in unique_list]
return unique_list
リスト内包表記を使用して副作用があると考えるのが良い解決策ではないと考える人もいるかもしれません。これが代替案です:
def make_unique(original_list):
unique_list = []
map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)
return unique_list
これまでに見てきたすべての次数保存アプローチは、単純比較(せいぜいO(n ^ 2)の時間複雑度)、またはハッシュ可能な入力に限定されたウェイトの高いOrderedDicts
name____/set
name____________list
name__の組み合わせを使用します。これはハッシュに依存しないO(nlogn)解です:
更新 key
name__引数、ドキュメントおよびPython 3互換性を追加しました。
# from functools import reduce <-- add this import on Python 3
def uniq(iterable, key=lambda x: x):
"""
Remove duplicates from an iterable. Preserves order.
:type iterable: Iterable[Ord => A]
:param iterable: an iterable of objects of any orderable type
:type key: Callable[A] -> (Ord => B)
:param key: optional argument; by default an item (A) is discarded
if another item (B), such that A == B, has already been encountered and taken.
If you provide a key, this condition changes to key(A) == key(B); the callable
must return orderable objects.
"""
# Enumerate the list to restore order lately; reduce the sorted list; restore order
def append_unique(acc, item):
return acc if key(acc[-1][1]) == key(item[1]) else acc.append(item) or acc
srt_enum = sorted(enumerate(iterable), key=lambda item: key(item[1]))
return [item[1] for item in sorted(reduce(append_unique, srt_enum, [srt_enum[0]]))]
セットを使ってみてください。
import sets
t = sets.Set(['a', 'b', 'c', 'd'])
t1 = sets.Set(['a', 'b', 'c'])
print t | t1
print t - t1
あなたもこれを行うことができます:
>>> t = [1, 2, 3, 3, 2, 4, 5, 6]
>>> s = [x for i, x in enumerate(t) if i == t.index(x)]
>>> s
[1, 2, 3, 4, 5, 6]
上記が機能するのは、index
メソッドが要素の最初のインデックスだけを返すからです。重複した要素はより高いインデックスを持ちます。 ここ を参照してください。
list.index(x [、start [、end]])
値がxである最初の項目ののリストにゼロから始まるインデックスを返します。 そのような項目がない場合はValueErrorを送出します。
もう1つ優れた方法があります。
import pandas as pd
myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanList = pd.Series(myList).drop_duplicates().tolist()
print(cleanList)
#> [1, 2, 3, 5, 6, 7, 8]
そして順序は保存されたままです。
セットを使わずに
data=[1, 2, 3, 1, 2, 5, 6, 7, 8]
uni_data=[]
for dat in data:
if dat not in uni_data:
uni_data.append(dat)
print(uni_data)
リストから重複したものを削除するための最善の方法は、Pythonで利用可能な set() 関数を使用し、その setをリストに変換することです
In [2]: some_list = ['a','a','v','v','v','c','c','d']
In [3]: list(set(some_list))
Out[3]: ['a', 'c', 'd', 'v']
これを行うにはさまざまな方法を提案する他の多くの答えがありますが、それらはすべてバッチ操作であり、それらのうちのいくつかは元の順序を破棄します。それはあなたが必要とするものによっては大丈夫かもしれません、しかし、もしあなたがそれぞれの値の最初のインスタンスの順序で値を反復したい、そしてあなたが全部対一度にその場で重複を取り除きたいこのジェネレータ
def uniqify(iterable):
seen = set()
for item in iterable:
if item not in seen:
seen.add(item)
yield item
これはジェネレータ/イテレータを返すので、イテレータを使用できる場所ならどこでも使用できます。
for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]):
print(unique_item, end=' ')
print()
出力:
1 2 3 4 5 6 7 8
もしあなたがlist
が欲しいなら、あなたはこれをすることができます:
unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]))
print(unique_list)
出力:
[1, 2, 3, 4, 5, 6, 7, 8]
以下のコードは、リスト内の重複を削除するのに簡単です。
def remove_duplicates(x):
a = []
for i in x:
if i not in a:
a.append(i)
return a
print remove_duplicates([1,2,2,3,3,4])
それは返します[1,2,3,4]
順序を維持しながらバリアントを減らす:
リストがあるとします。
l = [5, 6, 6, 1, 1, 2, 2, 3, 4]
バリアントを減らす(非効率的):
>>> reduce(lambda r, v: v in r and r or r + [v], l, [])
[5, 6, 1, 2, 3, 4]
5倍高速だがより洗練された
>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0]
[5, 6, 1, 2, 3, 4]
説明:
default = (list(), set())
# user list to keep order
# use set to make lookup faster
def reducer(result, item):
if item not in result[1]:
result[0].append(item)
result[1].add(item)
return result
reduce(reducer, l, default)[0]
以下の機能を使用することができます。
def rem_dupes(dup_list):
yooneeks = []
for elem in dup_list:
if elem not in yooneeks:
yooneeks.append(elem)
return yooneeks
例 :
my_list = ['this','is','a','list','with','dupicates','in', 'the', 'list']
使用法:
rem_dupes(my_list)
['this'、 'is'、 'a'、 'list'、 'with'、 'dupicates'、 'in'、 'the']
これはあまり手間をかけずに注文を気にかけます(OrderdDict&others)。おそらく最もPythonicの方法でも最短の方法でもありませんが、トリックを行います:
def remove_duplicates(list):
''' Removes duplicate items from a list '''
singles_list = []
for element in list:
if element not in singles_list:
singles_list.append(element)
return singles_list
これは、回答にリストされている他のものと比較して最も速いPythonicソリューションです。
短絡評価の実装詳細を使用すると、リスト内包表記を使用できます。これは十分に高速です。 visited.add(item)
は常にNone
を結果として返します。これはFalse
として評価されるため、or
の右側は常にそのような式の結果になります。
自分で時間を計る
def deduplicate(sequence):
visited = set()
adder = visited.add # get rid of qualification overhead
out = [adder(item) or item for item in sequence if item not in visited]
return out
set を使用します。
a = [0,1,2,3,4,3,3,4]
a = list(set(a))
print a
unique を使用します。
import numpy as np
a = [0,1,2,3,4,3,3,4]
a = np.unique(a).tolist()
print a
Python 3のとても簡単な方法:
>>> n = [1, 2, 3, 4, 1, 1]
>>> n
[1, 2, 3, 4, 1, 1]
>>> m = sorted(list(set(n)))
>>> m
[1, 2, 3, 4]
重複を削除するにはset
を使用できます。
mylist = list(set(mylist))
しかし、結果は順不同になることに注意してください。それが問題ならば:
mylist.sort()
組み込みのset、dict.keys、uniqify、counterを使用せずに重複を削除する(新しいリストを返すのではなくインプレース編集)場合は、これをチェックしてください。
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> for i in t:
... if i in t[t.index(i)+1:]:
... t.remove(i)
...
>>> t
[3, 1, 2, 5, 6, 7, 8]
これは、順序を維持した繰り返しのないリストを返す例です。外部からの輸入は必要ありません。
def GetListWithoutRepetitions(loInput):
# return list, consisting of elements of list/Tuple loInput, without repetitions.
# Example: GetListWithoutRepetitions([None,None,1,1,2,2,3,3,3])
# Returns: [None, 1, 2, 3]
if loInput==[]:
return []
loOutput = []
if loInput[0] is None:
oGroupElement=1
else: # loInput[0]<>None
oGroupElement=None
for oElement in loInput:
if oElement<>oGroupElement:
loOutput.append(oElement)
oGroupElement = oElement
return loOutput
Setへの変換が重複を取り除く最も簡単な方法だと思います
list1 = [1,2,1]
list1 = list(set(list1))
print list1
別の解決策は次のようになります。項目としてキー、インデックスとして値を使用してリストから辞書を作成し、辞書のキーを印刷します。
>>> lst = [1, 3, 4, 2, 1, 21, 1, 32, 21, 1, 6, 5, 7, 8, 2]
>>>
>>> dict_enum = {item:index for index, item in enumerate(lst)}
>>> print dict_enum.keys()
[32, 1, 2, 3, 4, 5, 6, 7, 8, 21]
ここではset(..)
(要素が hashable で与えられると速い)やリスト( O(nという結果になるというマイナス面があります)を使う答えがたくさんあります。2) アルゴリズム.
私が提案する関数はハイブリッドなものです。私たちは are hashableなアイテムにはset(..)
を使い、そうでないものにはlist(..)
を使います。さらにそれは ジェネレータ として実装されているので、例えばアイテムの数を制限したり、追加のフィルタリングを行うことができます。
最後に、key
引数を使用して、要素を一意にする方法を指定することもできます。たとえば、出力内のすべての文字列の長さが異なるように文字列のリストをフィルタ処理する場合は、これを使用できます。
def uniq(iterable, key=lambda x: x):
seens = set()
seenl = []
for item in iterable:
k = key(item)
try:
seen = k in seens
except TypeError:
seen = k in seenl
if not seen:
yield item
try:
seens.add(k)
except TypeError:
seenl.append(k)
たとえば、これを次のように使用できます。
>>> list(uniq(["Apple", "pear", "banana", "lemon"], len))
['Apple', 'pear', 'banana']
>>> list(uniq(["Apple", "pear", "lemon", "banana"], len))
['Apple', 'pear', 'banana']
>>> list(uniq(["Apple", "pear", {}, "lemon", [], "banana"], len))
['Apple', 'pear', {}, 'banana']
>>> list(uniq(["Apple", "pear", {}, "lemon", [], "banana"]))
['Apple', 'pear', {}, 'lemon', [], 'banana']
>>> list(uniq(["Apple", "pear", {}, "lemon", {}, "banana"]))
['Apple', 'pear', {}, 'lemon', 'banana']
したがって、それがハッシュ可能であるかどうかにかかわらず、任意の反復可能オブジェクトに対して機能し、一意性を排除することができる一意性フィルタです。
1つのオブジェクトがハッシュ可能で、別のオブジェクトがハッシュ可能でない場合、2つのオブジェクトは等しくなることはありません。これは厳密に言えば起こり得ますが、非常に珍しいことです。
あなたは単にセットを使うことによってこれをすることができます。
ステップ1: /リストのさまざまな要素を取得する
Step2 リストの共通要素を取得
Step3 結合する
In [1]: a = ["apples", "bananas", "cucumbers"]
In [2]: b = ["pears", "apples", "watermelons"]
In [3]: set(a).symmetric_difference(b).union(set(a).intersection(b))
Out[3]: {'apples', 'bananas', 'cucumbers', 'pears', 'watermelons'}
重複を削除するには、それをSETにしてから再びLISTにしてそれを印刷/使用します。例えば :
a = [1,2,3,4,5,9,11,15]
b = [4,5,6,7,8]
c=a+b
print c
print list(set(c)) #one line for getting unique elements of c
出力は以下のようになります(python 2.7でチェック済み)
[1, 2, 3, 4, 5, 9, 11, 15, 4, 5, 6, 7, 8] #simple list addition with duplicates
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15] #duplicates removed!!
def remove_duplicates(A):
[A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1]
return A
重複を削除するためのリストの理解
順序を気にせず、上で提案したPythonicの方法とは異なるものが必要な場合(つまり、インタビューで使用できます)。
def remove_dup(arr):
size = len(arr)
j = 0 # To store index of next unique element
for i in range(0, size-1):
# If current element is not equal
# to next element then store that
# current element
if(arr[i] != arr[i+1]):
arr[j] = arr[i]
j+=1
arr[j] = arr[size-1] # Store the last element as whether it is unique or repeated, it hasn't stored previously
return arr[0:j+1]
if __== '__main__':
arr = [10, 10, 1, 1, 1, 3, 3, 4, 5, 6, 7, 8, 8, 9]
print(remove_dup(sorted(arr)))
時間の複雑さ:O(n)
補助スペース:O(n)
参照: http://www.geeksforgeeks.org/remove-duplicates-sorted-array/ /
残念ながらここでのほとんどの答えは順序を保存しないかまたは長すぎます。これは簡単な、注文保存の答えです。
s = [1,2,3,4,5,2,5,6,7,1,3,9,3,5]
x=[]
[x.append(i) for i in s if i not in x]
print(x)
これはxを重複を取り除いても順序を保ったままにします。
新しいリストを作成せずに、重複した項目をその場で削除する必要がある場合があります。たとえば、リストが大きい場合や、シャドウコピーとして残しておく場合などです。
from collections import Counter
cntDict = Counter(t)
for item,cnt in cntDict.items():
for _ in range(cnt-1):
t.remove(item)
サードパーティ製のモジュールをインストールする必要がありますが、パッケージiteration_utilities
には unique_everseen
が含まれています。1 順序を維持しながらすべての重複を削除することができる関数:
>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen(['a', 'b', 'c', 'd'] + ['a', 'c', 'd']))
['a', 'b', 'c', 'd']
リスト追加操作のオーバーヘッドを避けたい場合は、代わりに itertools.chain
を使用できます。
>>> from itertools import chain
>>> list(unique_everseen(chain(['a', 'b', 'c', 'd'], ['a', 'c', 'd'])))
['a', 'b', 'c', 'd']
unique_everseen
は、もしあなたがリストの中に邪魔にならないアイテム(例えばリスト)がある場合にも働きます:
>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen([['a'], ['b'], 'c', 'd'] + ['a', 'c', 'd']))
[['a'], ['b'], 'c', 'd', 'a']
ただし、アイテムがハッシュ可能な場合よりも(はるかに)遅くなります。
1 開示:私はiteration_utilities
-ライブラリの作者です。
順序を保持したいが外部モジュールを使用したくない場合は、これを行う簡単な方法があります。
>>> t = [1, 9, 2, 3, 4, 5, 3, 6, 7, 5, 8, 9]
>>> list(dict.fromkeys(t))
[1, 9, 2, 3, 4, 5, 6, 7, 8]
注:この方法では外観の順序が保持されるため、上で見たように、最初に登場したのは9つあります。これは、しかし、あなたがやっているのと同じ結果です
from collections import OrderedDict
ulist=list(OrderedDict.fromkeys(l))
しかし、それははるかに短く、そして速く走ります。
これは、fromkeys
関数が新しいキーを作成しようとするたびに、その値がすでに存在する場合は単にそれを上書きするためです。ただし、fromkeys
はすべてのキーの値がNone
である辞書を作成するので、これは辞書にまったく影響を与えません。したがって、この方法ですべての重複を事実上排除します。
def remove_duplicates(input_list):
if input_list == []:
return []
#sort list from smallest to largest
input_list=sorted(input_list)
#initialize ouput list with first element of the sorted input list
output_list = [input_list[0]]
for item in input_list:
if item >output_list[-1]:
output_list.append(item)
return output_list
list_with_unique_items = list(set(list_with_duplicates))
これは単なる読解可能な機能で、簡単に理解できます。そして、私は辞書データ構造を使用しました。
def undup(dup_list):
b={}
for i in dup_list:
b.update({i:1})
return b.keys()
a=["a",'b','a']
print undup(a)
免責事項:uはコピー&ペーストの場合はインデントエラーが発生する可能性があります。貼り付ける前に適切なインデントを付けて上記のコードを使用してください
リストが順序付けされている場合は、以下のアプローチを使用して、繰り返される値をスキップしてそれを繰り返すことができます。これは、dict
またはset
を構築するコストを回避しながら、メモリ使用量の少ない大きなリストを処理するのに特に便利です。
def uniq(iterator):
prev = None
for item in iterator:
if item != prev:
prev = item
yield item
その後:
for item in [1, 1, 3, 5, 5, 6]:
print(item, end=' ')
出力は次のようになります。1 3 5 6
Pythonには多くの関数が組み込まれていますリストの中の重複を取り除くためにset()を使うことができます。
t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
result = list(set(t) - set(t2))
result
答え:['b']