◀ 6.

Python でリストの要素数を取得|len() の使い方と多次元・条件付きカウント

この記事の要点
  • リストの要素数は len(リスト)。list.length や .size() ではない
  • len() は要素の個数を数え直さない。内部に保持した値を返すので、要素が何万個あっても一瞬で返る
  • ネストしたリストは 外側の個数しか数えない。合計は sum(len(x) for x in ...)
  • 条件に合う個数は len([...]) より sum(1 for ...)。リストを作らないぶん省メモリ
  • 空かどうかを見たいだけなら if not items: と書く。len(items) == 0 は冗長

基本

fruits = ["りんご", "みかん", "ぶどう"]

print(len(fruits))       # 3
print(len([]))           # 0

# 添字の最大値は len() - 1
print(fruits[len(fruits) - 1])   # ぶどう
print(fruits[-1])                # ぶどう   こちらのほうが簡単

len() は組み込み関数なので import は不要です。メソッドではないため fruits.len() とは書けません。

リスト以外にも使える

print(len("こんにちは"))          # 5    文字数
print(len((1, 2, 3)))             # 3    タプル
print(len({"a": 1, "b": 2}))      # 2    辞書はキーの数
print(len({1, 2, 2, 3}))          # 3    集合は重複を除いた数
print(len(b"abc"))                # 3    バイト数
print(len(range(10)))             # 10

# len() が使えないもの
print(len(123))                   # TypeError: object of type 'int' has no len()
gen = (x for x in range(5))
print(len(gen))                   # TypeError   ジェネレータには長さが無い
print(sum(1 for _ in gen))        # 5   数えるなら消費するしかない

多次元リストの数え方

matrix = [[1, 2, 3], [4, 5], [6]]

print(len(matrix))                       # 3   行数(外側の個数)
print(len(matrix[0]))                    # 3   1 行目の列数

# 全要素の合計
print(sum(len(row) for row in matrix))   # 6

# 平らにしてから数える
flat = [v for row in matrix for v in row]
print(len(flat))                         # 6

# 各行の長さが揃っているか確認
print(len({len(row) for row in matrix}) == 1)   # False(バラバラ)

len(matrix) は「全部でいくつ入っているか」ではありません。行列を扱うなら NumPy の shape のほうが分かりやすくなります(多次元配列の構造の確認)。

条件に合う要素を数える

nums = [1, 2, 3, 4, 5, 6]

print(len([n for n in nums if n % 2 == 0]))   # 3   一度リストを作る
print(sum(1 for n in nums if n % 2 == 0))     # 3   リストを作らない(推奨)
print(sum(n % 2 == 0 for n in nums))          # 3   bool は int なので足せる

# 特定の値がいくつあるか
print(nums.count(3))                          # 1

# 種類ごとに数える
from collections import Counter
words = ["a", "b", "a", "c", "a"]
print(Counter(words))                # Counter({'a': 3, 'b': 1, 'c': 1})
print(Counter(words)["a"])           # 3
print(Counter(words).most_common(1)) # [('a', 3)]

件数が多いときは len([...]) だと中間リストがメモリに乗ります。数えるだけなら sum(1 for ...) のほうが軽量です。

空かどうかの判定

items = []

if not items:              # Pythonic
    print("空です")

# 以下は冗長。PEP 8 でも len() を使わない書き方が推奨されている
if len(items) == 0: ...
if items == []: ...

# None かもしれない場合は先に弾く
data = None
if data is None or len(data) == 0:
    print("データがありません")

# 1 行で書くなら
print(len(data or []))     # 0

None に len() を使うと TypeError: object of type 'NoneType' has no len() になります。関数の戻り値をそのまま数えるときは、None が返る可能性を先に確認します。

len() は速い

big = list(range(10_000_000))
print(len(big))            # 10000000   数え直さないので一瞬で返る

# ループのたびに呼んでも問題ないが、変わらない値なら外に出すと読みやすい
n = len(big)
for i in range(n):
    pass

リスト・タプル・辞書・集合は自分の要素数を内部に保持しているため、len() は要素数によらず一定時間です。「重いから変数に入れておく」必要はありません。

自作クラスで len() を使えるようにする

class Basket:
    def __init__(self):
        self.items = []

    def __len__(self):          # len() から呼ばれる
        return len(self.items)

b = Basket()
b.items.append("りんご")
print(len(b))       # 1
print(bool(b))      # True    __len__ が 0 以外なら真になる

__len__ を定義すると if b: の判定にも使われます。「空なら偽」という挙動が自動で付いてくる点は覚えておくと便利です。

ほかの言語からの移行

言語書き方Python
Javalist.size() / array.lengthlen(x)
JavaScriptarray.length
PHPcount($array)
C#list.Count / array.Length

Python は関数のかたちで統一されています。リストでも文字列でも辞書でも同じ len() で数えられるのが利点です。

要素数を使った処理

items = ["a", "b", "c", "d", "e"]

# 真ん中を取り出す
print(items[len(items) // 2])          # c

# 半分に分ける
half = len(items) // 2
print(items[:half], items[half:])      # ['a', 'b'] ['c', 'd', 'e']

# n 個ずつに区切る
n = 2
chunks = [items[i:i + n] for i in range(0, len(items), n)]
print(chunks)                          # [['a', 'b'], ['c', 'd'], ['e']]

# 2 つのリストの長さが揃っているか確認してから zip する
other = [1, 2, 3, 4, 5]
if len(items) != len(other):
    raise ValueError("件数が一致しません")
print(dict(zip(items, other)))

zip() は短いほうに黙って合わせます。件数が一致しているべき場面では、先に len() で確認するか zip(..., strict=True) を使ってください。

件数を扱うときの注意

# 文字数は「見た目の文字数」とは限らない
import unicodedata

s = unicodedata.normalize("NFD", "が")     # 濁点を分解した形
print(len(s))                              # 2   「か」+「濁点」
print(len(unicodedata.normalize("NFC", s)))# 1   結合した形に戻す

print(len("👨‍👩‍👦"))            # 5   絵文字は複数の文字の組み合わせ

# バイト数が必要な場面(ファイルサイズ・DB の桁数)
s = "あいう"
print(len(s))                   # 3   文字数
print(len(s.encode("utf-8")))   # 9   バイト数

入力欄の文字数制限やデータベースの桁数チェックでは、文字数とバイト数のどちらで数えるのかを決めておかないと、日本語で必ず食い違います。

関連

子ページ

子ページはありません

同階層のページ
  1. リストの作成
  2. 要素の参照
  3. リストへの要素追加(append / extend / insert / += / slice 代入)
  4. リスト要素の更新
  5. 要素の削除
  6. リスト要素数の取得