中学理科1630641 views
中学英語811710 views
雑学1473612 views
いろは3010814 views
LaTeX962153 views
小学算数1200427 views
世界の国564520 views
ヒストリア290598 views
高校倫理1440106 views
高校日本史190571 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Python の集合と内包表記

集合内包表記(set comprehension)を使うと、ループを使わずに簡潔に集合を構築できる。リスト内包表記と同じ構文で、波括弧を使う点が異なる。

基本構文

集合内包表記は {式 for 変数 in イテラブル} の形式で書く。

# 0 から 9 の 2 乗の集合
squares = {x ** 2 for x in range(10)}
print(squares)  # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

リスト内包表記 [x ** 2 for x in range(10)] と似ているが、結果は集合になる。重複は自動的に排除される。

# 重複が除去される
nums = {x % 3 for x in range(10)}
print(nums)  # {0, 1, 2}

0〜9 の各数を 3 で割った余りは 0, 1, 2 のいずれかなので、結果は 3 要素になる。

条件付き内包表記

if 節を追加して、条件を満たす要素だけを含めることができる。

# 偶数だけの集合
evens = {x for x in range(20) if x % 2 == 0}
print(evens)  # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}

条件は複数書ける。

# 3 でも 5 でも割り切れない数
nums = {x for x in range(30) if x % 3 != 0 if x % 5 != 0}
print(nums)  # {1, 2, 4, 7, 8, 11, 13, 14, 16, 17, 19, 22, 23, 26, 28, 29}

入れ子のループ

複数の for を連ねることで、入れ子のループを表現できる。

# 2 つのリストのすべての組み合わせの和
a = [1, 2, 3]
b = [10, 20, 30]
sums = {x + y for x in a for y in b}
print(sums)  # {11, 12, 13, 21, 22, 23, 31, 32, 33}

これは以下のループと同等だ。

sums = set()
for x in a:
    for y in b:
        sums.add(x + y)

文字列処理への応用

文字列から特定の文字を抽出するのに便利だ。

text = "Hello, World! 123"

# アルファベットのみ抽出(小文字化)
letters = {c.lower() for c in text if c.isalpha()}
print(letters)  # {'h', 'e', 'l', 'o', 'w', 'r', 'd'}

文字列中の母音だけを抽出する例もある。

vowels_in_text = {c for c in "programming" if c in "aeiou"}
print(vowels_in_text)  # {'o', 'a', 'i'}

辞書からの集合生成

辞書のキーや値から集合を作ることもできる。

scores = {"alice": 85, "bob": 92, "charlie": 78, "dave": 85}

# 値(スコア)のユニークな集合
unique_scores = {v for v in scores.values()}
print(unique_scores)  # {78, 85, 92}

# 80 点以上の人の集合
high_scorers = {k for k, v in scores.items() if v >= 80}
print(high_scorers)  # {'alice', 'bob', 'dave'}

式の変換

式の部分で変換処理を行える。

words = ["Apple", "Banana", "Cherry", "apple", "BANANA"]

# 小文字に正規化した集合
normalized = {w.lower() for w in words}
print(normalized)  # {'apple', 'banana', 'cherry'}

変換後に重複が発生しても、集合なので自動的に 1 つにまとまる。

条件式(三項演算子)との組み合わせ

式の中で条件分岐もできる。

numbers = [-3, -1, 0, 1, 3, 5]

# 正の数はそのまま、負の数は絶対値に
result = {x if x > 0 else -x for x in numbers}
print(result)  # {0, 1, 3, 5}

if x > 0 else -x は条件式で、内包表記の if フィルタとは別物だ。

フィルタの if

for x in ... if 条件 の形。条件を満たす要素だけを処理。

条件式の if

値1 if 条件 else 値2 の形。式の中で値を切り替え。

frozenset の内包表記

frozenset には専用の内包表記がないため、frozenset() で包む。

fs = frozenset({x ** 2 for x in range(5)})
print(fs)  # frozenset({0, 1, 4, 9, 16})

一度 set を作ってから frozenset に変換している。

ジェネレータ式との違い

丸括弧を使うとジェネレータ式になり、集合ではなくなる。

# 集合内包表記
s = {x for x in range(5)}
print(type(s))  # <class 'set'>

# ジェネレータ式
g = (x for x in range(5))
print(type(g))  # <class 'generator'>

ジェネレータは遅延評価されるため、大量データを扱う際はメモリ効率がよい。集合が必要なら set() で包む。

large_set = set(x ** 2 for x in range(1000000))

可読性の考慮

複雑な内包表記は可読性が下がる。以下のような場合は通常のループのほうがよい。

# 複雑すぎる例
result = {
    (x, y, z)
    for x in range(10)
    for y in range(10)
    for z in range(10)
    if x + y + z == 15
    if x < y < z
}

このような場合は、関数に切り出すか通常のループで書くほうが読みやすい。

def find_triplets(total, limit):
    result = set()
    for x in range(limit):
        for y in range(x + 1, limit):
            z = total - x - y
            if y < z < limit:
                result.add((x, y, z))
    return result

print(find_triplets(15, 10))

内包表記は 1〜2 行で収まる程度の複雑さに抑えるのが望ましい。