芋の独り言

当ブログへのアクセスは当ブログのプライバシーポリシーに同意したものとみなします.

Python list私的メモ

要素の削除

remove

>>> p=[5,7,2,8,3,None,None,None,7,None]
>>> len(p)
10
>>> p.remove(None)
>>> p
[5, 7, 2, 8, 3, None, None, 7, None]
>>> len(p)
9
>>> p.remove(9)
Traceback (most recent call last):
  File "<pyshell#153>", line 1, in <module>
    p.remove(9)
ValueError: list.remove(x): x not in list

removeは最初に見つけた,引数で渡されたものと同じ値の要素を削除する. removeは元のリストが変更されるようである.なので,要素数が前後で異なっている.

余談:helpでリストの使い方を見る&一度に要素を複数削除する方法

ということで,removeでは最初に見つけた要素1つしか削除できない.つまり,一度に複数の削除ができない. ということで,何かないかと思い,

>>> help(list)
Help on class list in module builtins:

class list(object)
 |  list(iterable=(), /)
 |  
 |  Built-in mutable sequence.
 |  
 |  If no argument is given, the constructor creates a new empty list.
 |  The argument must be an iterable if specified.
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(self, /)
 |      Return a reverse iterator over the list.
 |  
 |  __rmul__(self, value, /)
 |      Return value*self.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(self, /)
 |      Return the size of the list in memory, in bytes.
 |  
 |  append(self, object, /)
 |      Append object to the end of the list.
 |  
 |  clear(self, /)
 |      Remove all items from list.
 |  
 |  copy(self, /)
 |      Return a shallow copy of the list.
 |  
 |  count(self, value, /)
 |      Return number of occurrences of value.
 |  
 |  extend(self, iterable, /)
 |      Extend list by appending elements from the iterable.
 |  
 |  index(self, value, start=0, stop=9223372036854775807, /)
 |      Return first index of value.
 |      
 |      Raises ValueError if the value is not present.
 |  
 |  insert(self, index, object, /)
 |      Insert object before index.
 |  
 |  pop(self, index=-1, /)
 |      Remove and return item at index (default last).
 |      
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(self, value, /)
 |      Remove first occurrence of value.
 |      
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(self, /)
 |      Reverse *IN PLACE*.
 |  
 |  sort(self, /, *, key=None, reverse=False)
 |      Stable sort *IN PLACE*.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

っとやってみたが,複数削除できるメソッドはなさそうだ.なので,以下のようにremoveValueErrorが出るまで繰り返し呼ぶしかなさそう...ほかに方法があれば教えていただきたい...

>>> while True:
    try:
        p.remove(None)
    except ValueError:
        break

    
>>> p
[5, 7, 2, 8, 3, 7]
>>> len(p)
6

del

他のリストの要素削除方法として,

>>> p=[1,5,8,7,4]
>>> p.__len__()
5
>>> del p[0]
>>> p
[5, 8, 7, 4]
>>> q = 1
>>> del q

という方法がある.delはリスト専用ではなく,変数等のメモリの開放にも使えたはず. スクリプト内で必要なくなった変数はdelで適宜メモリ開放しておくと,メモリエラーで困ることを避けやすいだろう. 以上のようにリストの要素を指定すると,その部分を削除したように見える.要素番号でリストの要素を指定して削除したい場合はremoveではなく,delを使うとよい.popというメソッドについては触れない.

要素の検索

>>> p.index(8)

とやると,その要素の値のindex値が得られる. リストにその要素がない場合はValueErrorが起きるので,これを使えばリスト内に所望の要素があるか検索できる.

重複する要素の表示と削除

from collections import Counter

a = [0,5,6,0,2,3,0,5]
# 重複部分を削除:set型は重複を認めない
b = set(a)
# 重複する要素の表示
if (len(a)-len(b) != 0:
    print('重複あり')
    print('------重複部分------')
    for k,v in Counter(a).items():
        if v > 1:
            print(k)

Counterで要素の出現回数を数えた時,1以上の場合は重複している.なので,以上のようにすれば,重複要素の表示ができる. 重複部分の削除は簡単で,set型にしてやればいい.set型では重複する要素は自動で消されるためである. ただし,set型は順序を保持しないので,順番がバラバラになってしまう. set型にはsortメソッドがない.sortメソッドがあるのはlist型である. そこで,順番に並べておくには,

b = list(set(a))
# 昇順
b.sort()
# 降順
b.sort(reverse=True)

としておくとよい.sortメソッドは値を返却せず,元のリストを上書きするので, b=list(set(a)).sort()とやると変数bには値が何も入っていないこと(NoneType)になるので注意する.
↓参考
collections --- コンテナデータ型 — Python 3.7.4 ドキュメント

余談

>>> o=[[0,4],[7,8],[8,9]]

という2次元リストを用意したとき,このリストを

\begin{pmatrix}
0 \quad 4 \\
7 \quad 8 \\
8 \quad 9 \\
\end{pmatrix}

と考えたとき,1列目の要素を何個か抽出したいとき,どうすればよいか?

>>> o[0:1][0]
[0, 4]
>>> o[0:1]
[[0, 4]]
>>> o[0:2][0]
[0, 4]
>>> o[0:2]
[[0, 4], [7, 8]]
>>> [x[0] for x in o[0:1]]
[0]
>>> [x[0] for x in o[0:2]]
[0, 7]

以上からの結論はリストのスライシングと内包表記を組み合わせて使うこと.また,スライシングする際に,終了値は含まれない.そのため,

[x[取りたい要素番号] for x in o[初期値(これは抽出される):終了値(これは含まれない)+1]

とするのがよい.